1

I am not able to twist my head into understanding how to get Powershell to loop the entire JSON Structure, it wont' loop the System.Object[]

$x = ConvertFrom-Json '{
    "Car companies": {
        "Name of Company": "Ford",
        "Cars": [{
            "Name of car": "Ranger",
            "Config": "Pickup"
        },
        {
            "Name of car": "Puma",
            "Config": "Hatchback"
        }]
     }
 }'

foreach( $rootProperty in @($x.psobject.properties | where-object {$_.MemberType -eq "NoteProperty"}) )    {
    write-host " - '$($rootProperty.Name)' = '$($rootProperty.Value)'"
    foreach( $childProperty in @($rootProperty.Value.psobject.properties ) ) {
        write-host "'$($childProperty.Name)' = '$($childProperty.Value)'"
   }
}

Outut I get now is just

- 'Brand' = '@{Name of Brand=Ford; Cars=System.Object[]}'
   Name of Brand' = 'Ford'
   Cars' = ' '

...as a follop How to iterate through a unknown JSON data/object?

mklement0
  • 382,024
  • 64
  • 607
  • 775
rhellem
  • 769
  • 1
  • 11
  • 26

1 Answers1

2

tl;dr

You're seeing a bug that unexpectedly string-expands the Cars property value's array elements to the empty string.

A simple workaround - for display purposes only - is to pipe the property value to Out-String to get the usual display representation:

"'$($childProperty.Name)' = '$($childProperty.Value | Out-String)'"

You're seeing a bug in how arrays of [pscustomobject] instances are stringified (as of PowerShell Core 7.0.0-preview.6):

Generally, PowerShell arrays are stringified by joining the stringified element representations with the separator specified in the $OFS preference variable, which defaults to a space char.

Normally, [pscustomobject] instances have a string representation that resembles a hashtable literal (but isn't one); e.g.:

PS> $custObj = [pscustomobject] @{ foo = 'bar' }; "$custObj"
@{foo=bar}  # string representation that *resembles* a hashtable literal

Unexpectedly - and this is the bug - when custom objects are the elements of an array, they stringify to the empty string, which is what you saw:

PS> $custObj = [pscustomobject] @{ foo = 'bar' }; $arr = $custObj, $custObj; "[$arr]"
[ ] # !! Bug: custom objects stringified to empty strings, joined with a space

This is an indirect manifestation of a long-standing bug reported in this GitHub issue: that is, elements of an array being stringified are stringified by calls to their .ToString() method, and calling .ToString() on custom objects unexpectedly yields the empty string (unlike the string representation you get when you directly reference a single custom object in an expandable string, as shown above).

mklement0
  • 382,024
  • 64
  • 607
  • 775