1

I want to join programmatically json data from a master and a details list. A simplified example of my code would be:

$master = '[{"Sample": 1.3085},{"Sample":  1.4567}]' | ConvertFrom-Json
$detail = '[{"foo":1, "bar":2},{"foo":3, "bar":4}]' | ConvertFrom-Json

$master  | %{ 
    $_ | Add-Member -MemberType NoteProperty -Name 'Detail' -Value $detail -PassThru
} | ConvertTo-Json  

I expect this:

[{
        "Sample": 1.3085,
        "Detail": [
                {"foo" :1, "bar":2},
                {"foo" :3, "bar":4}
            ]
        }
    }, {
        "Sample": 1.4567,
        "Detail": [
                {"foo" :1, "bar":2},
                {"foo" :3, "bar":4}
            ]
        }
    }
]

But I get that:

[{
        "Sample": 1.3085,
        "Detail": {
            "value": [
                "@{foo=1; bar=2}",
                "@{foo=3; bar=4}"
            ],
            "Count": 2
        }
    }, {
        "Sample": 1.4567,
        "Detail": {
            "value": [
                "@{foo=1; bar=2}",
                "@{foo=3; bar=4}"
            ],
            "Count": 2
        }
    }
]

It would appear to me that the Add-Member snippet converts the PSObject value to a string instead off taking it as-is.

Also: when the $master array contains only one element it works better, though not as expected, but if there are more than one it does the string-ified result shown above.

This is the results with one single item in $master:

{
    "Sample":  1.3085,
    "Detail":  {
                   "value":  [
                                 {
                                     "foo":  1,
                                     "bar":  2
                                 },
                                 {
                                     "foo":  3,
                                     "bar":  4
                                 }
                             ],
                   "Count":  2
               }
}

What am I doing wrong?

Philippe Raemy
  • 393
  • 5
  • 10

2 Answers2

1

There are two problems with your code:

  • You're running into a bug still present in Windows PowerShell, but since fixed in Powershell Core, which causes the unwanted value and Count properties to appear in arrays - see this GitHub issue.

  • In order to ensure that the full depth of your input object tree is converted to JSON, you need to increase the default -Depth to (at least) match the actual depth.[1]

Fixing both problems yields:

# Windows PowerShell workaround for array-serialization bug.
# See https://github.com/PowerShell/PowerShell/issues/3222
Remove-TypeData -ErrorAction Ignore System.Array

$master = '[{"Sample": 1.3085},{"Sample":  1.4567}]' | ConvertFrom-Json
$detail = '[{"foo":1, "bar":2},{"foo":3, "bar":4}]' | ConvertFrom-Json

$master | ForEach-Object { 
  $_ | Add-Member -MemberType NoteProperty -Name 'Detail' -Value $detail -PassThru
} | ConvertTo-Json -Depth 3  # Note the required -Depth value.

[1] Perhaps surprisingly, -Depth defaults to 2, which is a frequent pitfall for users - see this question.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Alright so after messing around with this for a while this is as close as I can get.

$master = '[{"Sample":1.3085},{"Sample":1.4567}]'

$detail = '[{"foo":1,"bar":2},{"foo":3,"bar":4}]'

$master = ConvertFrom-Json -InputObject $master
$detail = ConvertFrom-Json -InputObject $detail

$i = 0
$master | % { 

$_ | Add-Member -Name 'Detail' -Value $detail.GetValue($i) -MemberType NoteProperty -PassThru

$i++
} | ConvertTo-Json -Depth 3

There is a problem when adding the new members to the [PSCustomObject], nothing is specifying where each value should go. Instead it is just appending all values to the new 'Detail' member. I was able to bypass this by running through a foreach loop and each iteration adds 1 to the variable $i

SysEngineer
  • 354
  • 1
  • 7