/flags/powershell/convertto-json-depth
ConvertTo-Json -Depth: why nested objects become strings like System.Collections.Hashtable
- tool
- PowerShell
- command
- ConvertTo-Json
- flag
- -Depth
- default
- 2
ConvertTo-Json converts only two levels of nested objects by default. Anything deeper is replaced by its .ToString() value, so nested hashtables become "System.Collections.Hashtable" and arrays become space-separated strings. Pass a larger -Depth:
$config | ConvertTo-Json -Depth 10See the difference
$config = [ordered]@{
name = 'app'
db = [ordered]@{ primary = [ordered]@{ host = 'db01'; ports = @(5432, 5433) } }
limits = [ordered]@{ cpu = [ordered]@{ max = 2 } }
}
'--- default (-Depth 2):'
$config | ConvertTo-Json -Compress
'--- -Depth 5:'
$config | ConvertTo-Json -Depth 5 -CompressOutput
--- default (-Depth 2):
{"name":"app","db":{"primary":{"host":"db01","ports":"5432 5433"}},"limits":{"cpu":{"max":2}}}
--- -Depth 5:
{"name":"app","db":{"primary":{"host":"db01","ports":[5432,5433]}},"limits":{"cpu":{"max":2}}}Windows PowerShell 5.1 truncates without any message. PowerShell 7.1 and later print a warning when the output was truncated, which makes the problem visible but does not fix it.
Details
| Item | Value |
|---|---|
| Default depth | 2 |
| Maximum | 100 |
| What counts as a level | each nested object, hashtable or array below the top object |
| -Compress | no whitespace or line breaks |
| -AsArray (PowerShell 7) | always output a JSON array, even for one object |
| -EnumsAsStrings (PowerShell 7) | enum values as names instead of numbers |
A single item piped in is not an array
@(1) | ConvertTo-Json -Compress
ConvertTo-Json -InputObject @(1) -CompressOutput
1 [1]
Piping sends the elements one by one, so a one-element array becomes a scalar. Use -InputObject (or -AsArray in PowerShell 7) when the receiver expects an array.
When the default bites
The two-level default was chosen to stop PowerShell from serializing enormous .NET object graphs. It surprises people in three common situations:
- Configuration files. Reading a JSON file with
ConvertFrom-Json, changing one value and writing it back withConvertTo-Jsonflattens everything below the second level. Always write back with an explicit-Depth. - REST request bodies. A body built from nested hashtables for
Invoke-RestMethod(Microsoft Graph, Azure, GitHub) arrives with"System.Collections.Hashtable"in place of the inner objects, and the API rejects the request or stores the wrong value. See Invoke-WebRequest vs Invoke-RestMethod. - Logging objects. Dumping an object to a log file shows inner properties as type names, which hides the values you wanted to see.
Limits and version differences
try { @{ a = 1 } | ConvertTo-Json -Depth 101 -ErrorAction Stop } catch { $_.Exception.Message }
'--- a DateTime in Windows PowerShell 5.1:'
[pscustomobject]@{ when = [datetime]::new(2026, 1, 2, 3, 4, 5, [DateTimeKind]::Utc) } | ConvertTo-Json -CompressOutput
The maximum depth allowed for serialization is 100.
--- a DateTime in Windows PowerShell 5.1:
{"when":"\/Date(1767323045000)\/"}| Behaviour | Windows PowerShell 5.1 | PowerShell 7 |
|---|---|---|
| Truncation beyond -Depth | silent | warning printed, output still truncated |
| Dates | "/Date(milliseconds)/" string | ISO 8601 string |
| Enums | numeric value | numeric value, or the name with -EnumsAsStrings |
| Single object to array | use -InputObject @(...) | -AsArray or -InputObject |
How to choose a depth
Count the levels of your data below the top object and add a margin: -Depth 10 covers almost every configuration file and API body. Avoid a high depth on live objects returned by system cmdlets; select the properties you need with Select-Object first, which keeps the JSON small and readable. If the data is tabular rather than nested, CSV may be the better format: Export-Csv -NoTypeInformation.
FAQ
Why not always use -Depth 100?
For your own hashtables and custom objects a high depth is harmless. For live .NET objects such as Get-Process or Get-Item results, a high depth walks huge object graphs and can produce megabytes of JSON, so select the properties you need first.
What happens if I pass -Depth 101?
The command fails with 'The maximum depth allowed for serialization is 100.' in Windows PowerShell 5.1; 100 is the upper limit.
Does ConvertFrom-Json also lose nested data?
Not in normal use. ConvertFrom-Json reads nested JSON fully; in PowerShell 6.2 and later its -Depth parameter defaults to 1024 and only stops pathological documents.