ConvertTo-Json turns PowerShell objects, hashtables and arrays into JSON text. Pipe the data to it, and use [ordered] so the keys keep your order:
$employee = [ordered]@{
Name = 'Alice Johnson'
Office = 'Austin'
Skills = 'PowerShell', 'Azure'
}
$employee | ConvertTo-Json
Output in PowerShell 7:
{
"Name": "Alice Johnson",
"Office": "Austin",
"Skills": [
"PowerShell",
"Azure"
]
}
Output in Windows PowerShell 5.1:
{
"Name": "Alice Johnson",
"Office": "Austin",
"Skills": [
"PowerShell",
"Azure"
]
}

Both are valid JSON with the same data, only the spacing differs. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1 and point out each difference.
Compact JSON with -Compress
-Compress removes the spaces and line breaks, which is what APIs and log files usually want:
[ordered]@{ Name = 'Alice Johnson'; Office = 'Austin' } | ConvertTo-Json -Compress
Output:
{"Name":"Alice Johnson","Office":"Austin"}
Convert an array of objects
An array of objects becomes a JSON array, and $true and $false become true and false:
$servers = @(
[pscustomobject]@{ Name = 'WEB01'; Role = 'Web'; Online = $true }
[pscustomobject]@{ Name = 'SQL01'; Role = 'Database'; Online = $false }
)
$servers | ConvertTo-Json -Compress
Output:
[{"Name":"WEB01","Role":"Web","Online":true},{"Name":"SQL01","Role":"Database","Online":false}]
A one-item array loses its brackets
When you pipe a single-item array, the pipeline unrolls it and ConvertTo-Json sees one value. Pass it with -InputObject to keep the array:
$list = @('WEB01')
"Piped: $($list | ConvertTo-Json -Compress)"
"-InputObject: $(ConvertTo-Json -InputObject $list -Compress)"
Output:
Piped: "WEB01"
-InputObject: ["WEB01"]

This bites when an API expects a list and your filter happens to return one item. PowerShell 7 also has -AsArray, shown at the end.
Nested data needs -Depth
ConvertTo-Json only serializes two levels deep by default. Deeper data turns into a type name, which creating JSON files shows in full. Add -Depth for nested settings, such as -Depth 5.
Dates and enums
Dates are where the two versions differ most. PowerShell 7 writes ISO 8601, while 5.1 writes an old Microsoft format:
$when = [datetime]::SpecifyKind([datetime]'2026-09-28 14:30', 'Utc')
"As a DateTime: $(@{ Updated = $when } | ConvertTo-Json -Compress)"
"As text: $(@{ Updated = $when.ToString('o') } | ConvertTo-Json -Compress)"
Output in PowerShell 7:
As a DateTime: {"Updated":"2026-09-28T14:30:00Z"}
As text: {"Updated":"2026-09-28T14:30:00.0000000Z"}
Output in Windows PowerShell 5.1:
As a DateTime: {"Updated":"\/Date(1790605800000)\/"}
As text: {"Updated":"2026-09-28T14:30:00.0000000Z"}
Convert dates to text with ToString(‘o’) first, and every system reads them the same way. Enums, like the day of the week, come out as numbers in both versions:
$day = ([datetime]'2026-09-28').DayOfWeek
"Enum: $(@{ Day = $day } | ConvertTo-Json -Compress)"
"As a string: $(@{ Day = $day.ToString() } | ConvertTo-Json -Compress)"
Output:
Enum: {"Day":1}
As a string: {"Day":"Monday"}
Convert a string to JSON, and JSON text to objects
A plain string becomes a quoted JSON string with its quotes escaped. To go the other way, from JSON text to objects, use ConvertFrom-Json:
$text = 'Order 1042 shipped to "Austin, TX"'
$text | ConvertTo-Json
$json = '{ "Order": 1042, "City": "Austin", "Paid": true }'
$order = $json | ConvertFrom-Json
"Order $($order.Order) for $($order.City), paid: $($order.Paid)"
Output:
"Order 1042 shipped to \"Austin, TX\""
Order 1042 for Austin, paid: True
ConvertFrom-Json gives you objects with real properties, so $order.City just works. The ConvertFrom-Json documentation covers -Depth for reading.
Validate JSON text
Catching a ConvertFrom-Json error is the usual check, but PowerShell 7 accepts a trailing comma that 5.1 rejects:
$good = '{ "Order": 1042 }'
$bad = '{ "Order": 1042, }'
foreach ($json in $good, $bad) {
try { $null = $json | ConvertFrom-Json -ErrorAction Stop; "Valid: $json" }
catch { "Invalid: $json" }
}
Output in PowerShell 7:
Valid: { "Order": 1042 }
Valid: { "Order": 1042, }
Output in Windows PowerShell 5.1:
Valid: { "Order": 1042 }
Invalid: { "Order": 1042, }
For a strict check in PowerShell 7, use Test-Json, which rejects the trailing comma.
If your data starts out as YAML instead, see how to convert YAML to JSON in PowerShell.
Extra options in PowerShell 7
PowerShell 7 adds -AsArray, -EnumsAsStrings and the Test-Json cmdlet. None of them exist in Windows PowerShell 5.1:
"-AsArray: $(@('WEB01') | ConvertTo-Json -Compress -AsArray)"
"-EnumsAsStrings: $(@{ Day = ([datetime]'2026-09-28').DayOfWeek } | ConvertTo-Json -Compress -EnumsAsStrings)"
"Test-Json good: $(Test-Json -Json '{ "Order": 1042 }')"
"Test-Json bad: $(Test-Json -Json '{ "Order": 1042, }' -ErrorAction SilentlyContinue)"
Output in PowerShell 7:
-AsArray: ["WEB01"]
-EnumsAsStrings: {"Day":"Monday"}
Test-Json good: True
Test-Json bad: False
