Skip to content

/flags/powershell/convertto-json-depth

ConvertTo-Json -Depth: why nested objects become strings like System.Collections.Hashtable

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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:

powershell
$config | ConvertTo-Json -Depth 10

See the difference

powershell
$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 -Compress

Output

--- 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

ItemValue
Default depth2
Maximum100
What counts as a leveleach nested object, hashtable or array below the top object
-Compressno 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

powershell
@(1) | ConvertTo-Json -Compress
ConvertTo-Json -InputObject @(1) -Compress

Output

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 with ConvertTo-Json flattens 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

powershell
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 -Compress

Output

The maximum depth allowed for serialization is 100.
--- a DateTime in Windows PowerShell 5.1:
{"when":"\/Date(1767323045000)\/"}
BehaviourWindows PowerShell 5.1PowerShell 7
Truncation beyond -Depthsilentwarning printed, output still truncated
Dates"/Date(milliseconds)/" stringISO 8601 string
Enumsnumeric valuenumeric value, or the name with -EnumsAsStrings
Single object to arrayuse -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.

Sources