simsaull simsaull - 2 months ago 14
JSON Question

Nested arrays and ConvertTo-Json

To use a REST API, I must pass a JSON object that looks like this:

{ "series" :
[{
"metric": "custom.powershell.gauge",
"points":[[1434684739, 1000]]
}
]
}


Note the nested array here. I cannot get to reproduce this. Here is my code:

[int][double]$unixtime=get-date ( (get-date).ToUniversalTime() ) -UFormat %s
$obj=@{}
$series=@{}
$array=@()
$points=@()
$value=get-random -Minimum 0 -Maximum 100


$series.add("metric","custom.powershell.gauge")
$points=@(@($unixtime, $value))
$series.add("points",$points)
$obj.Add("series",@($series))

$json=$obj | ConvertTo-Json -Depth 30 -Compress
$json


And here is the output:

{"series":[{"points":[1434685292,95],"metric":"custom.powershell.gauge"}]}


I've tried many things, I cannot get the 2 arrays to be nested, it always end up looking like a single array.

On the same note, came someone explain this please:

> $a=(1,2)
> $a
1
2
> $a | ConvertTo-Json
[
1,
2
]
> $b=($a,$a)
> $b
1
2
1
2
> $b | ConvertTo-Json
[
{
"value": [
1,
2
],
"Count": 2
},
{
"value": [
1,
2
],
"Count": 2
}
]


Where are these
value
and
Count
coming from?

Thanks for your help.

Answer

The explanation is that (1,2),(3,4) is an array of array, but Powershell split the first level with the pipe |, and you don't give a name for these arrays so the serializer supplies it. First have a try to this :

# First build your array of array
$z = (1,2),(3,4)
# convert it to JSON using the ,
,$z | ConvertTo-Json -Depth 5 -Compress
[psobject]@{"points"=$z} | ConvertTo-Json -Depth 5 -Compress

It gives the first step:

{"value":[[1,2],[3,4]],"Count":2}
{"points":[[1,2],[3,4]]}

Now the solution I propose :

# First build your array of array
$z = (1,2),(3,4)

# Then build a PSCustom object
$a = [pscustomobject]@{"series" = ,@{"metric"="custom.powershell.gauge"; "points"=$z}}

# At the end convert it to JSON
# don't forget the **Depth** parameter (use **Compress** to retreive one line like above)
$a | ConvertTo-Json -Depth 5

For me it gives something close to what you need:

{
    "series":  [
                   {
                       "points":  [
                                      [
                                          1,
                                          2
                                      ],
                                      [
                                          3,
                                          4
                                      ]
                                  ],
                       "metric":  "custom.powershell.gauge"
                   }
               ]
}