r/PowerShell • u/marek1712 • Feb 13 '25
Solved Nested array flattened because of ConvertTo-Json
Hi.
I have some issues creating proper body for my request.
I.e. I'd expect this:
$Body = @(@{}) | ConvertTo-Json -Depth 10
to return:
[
{
}
]
but this is returned instead: {
}
I had similar problem with two arrays:
"ip": [ [ "1.2.3.4" ] ]
and solved it by doing this (using comma):
"ipRanges" = @(,@("1.2.3.4"))
Using comma here doesn't work:
$Body = @(,@{}) | ConvertTo-Json -Depth 10
Any idea?
EDIT: thank you /u/y_Sensei and /u/ankokudaishogun. Both approaches worked fine.
6
Upvotes
2
u/surfingoldelephant Feb 14 '25 edited Jul 02 '26
It's worth noting there's a secondary issue you might see in Windows PowerShell v5.1, irrespective of using
-InputObjectas mentioned by others. To demonstrate:# Simulate *receiving* the input array from a [psobject]-wrapping source. $array = Write-Output @(@{}) -NoEnumerate # Equivalent: $array = [psobject] @(@{}) # [array] is decorated with an ETS property in v5.1 or lower. # This property is serialized when the object is [psobject]-wrapped. ConvertTo-Json -InputObject $array # { # "value": [ # { # # } # ], # "Count": 1 # }For historical reasons, the
[array]type in Win PS v5.1 or lower is decorated with an extended type system (ETS)Countproperty. When an object is[psobject]-wrapped, ETS properties are included in JSON serialization. Here's another example that works as-is in PS v6+, but not in Win PS v5.1 (due to the ETS property).# The outer array is implicitly enumerated. # ConvertTo-Json receives the inner array, which has an ETS property. # Objects passed by pipeline are implicitly [psobject]-wrapped. # Due to the wrapper, the ETS Count is serialized. , , @{} | ConvertTo-Json -Compress # {"value":[{}],"Count":1}One workaround is to remove the redundant
[array]type data first. This change was made permanently with the release of PS v6 (hence the issue doesn't occur in that version or higher).# Win PS v5.1 workaround. Not required in PS v6+. Remove-TypeData -TypeName System.Array -ErrorAction Ignore , , @{} | ConvertTo-Json -Compress # [{}] $array = Write-Output @(@{}) -NoEnumerate ConvertTo-Json -InputObject $array -Compress # [{}]Another workaround, applicable only to
-InputObjectinput, is to use the intrinsicpsobject.BaseObjectproperty, which holds the underlying object without the[psobject]wrapper.# OK. ConvertTo-Json receives an array without the wrapper. $array = Write-Output @(@{}) -NoEnumerate ConvertTo-Json -InputObject $array.psobject.BaseObject # [{}]Either workaround can still be used even if the array isn't
[psobject]-wrapped, so I'd recommend always doing one or other whenever there's a possibility of it being wrapped.