Home > Software engineering >  Converting complex Powershell objects into Json with arrays of single elements
Converting complex Powershell objects into Json with arrays of single elements

Time:08-06

I am trying to construct a complex powershell object containing nested hashtables and arrays, and then using the ConvertTo-Json function to convert the whole lot into Json.

I am experiencing a problem where - if an array object has only a single element, the Json that is returned is not returned as an array but as a single object. That is to say, it is missing the enclosing square brackets in the json.

Here is some sample code that demonstrates the problem:

function GetMyArrayData
{
    param($myData)

    $myArrayOfInfo = $myData  -split '\s*[,;]\s*'

    $myReturnArray = @()

    foreach($infoItem in $myArrayOfInfo)
    {
        $hashObj = @{
            field1 = "standard-value"
            field2 = $infoItem
        }

        $myReturnArray  = $hashObj
    }
    return $myReturnArray
}

$myFirstArray = GetMyArrayData -myData "abc;def"

$mySecondArray = GetMyArrayData -myData "xyz"

$myBigObject = @{
    item1 = "my-first-item"
    item2 = "my-second-item"
    myArray1 = $myFirstArray
    myArray2 = $mySecondArray
}

$myJsonVersion = ConvertTo-Json $myBigObject -Depth 5

Write-Output $myJsonVersion

This code then outputs the following JSON:

{
    "item2":  "my-second-item",
    "myArray1":  [
                     {
                         "field1":  "standard-value",
                         "field2":  "abc"
                     },
                     {
                         "field1":  "standard-value",
                         "field2":  "def"
                     }
                 ],
    "myArray2":  {
                     "field1":  "standard-value",
                     "field2":  "xyz"
                 },
    "item1":  "my-first-item"
}

Notice that "myArray2" is converted to a single object, rather than an array containing a single object.

It should be rendered thus:

{
    "item2":  "my-second-item",
    "myArray1":  [
                     {
                         "field1":  "standard-value",
                         "field2":  "abc"
                     },
                     {
                         "field1":  "standard-value",
                         "field2":  "def"
                     }
                 ],
    "myArray2":  [
                     {
                         "field1":  "standard-value",
                         "field2":  "xyz"
                     }
                 ],
    "item1":  "my-first-item"
}

Can anyone advise what is wrong with this code that prevents it from outputting myArray2 as an array containing a single object?

Thanks heaps,

David :-)

CodePudding user response:

When you return arrays and collections from a function PwerShell will “unroll” them. If the array contains a single object, it will return that object rather than an array.

You can work around this in a couple of ways - inside your function you can do this:

return @(, $myReturnArray )

which wraps your return value in an outer array - Powershell will then unroll that rather than your inner array, so your single item array is returned intact, or you can do this:

$myFirstArray = @( GetMyArrayData -myData "abc;def" )

which wraps the return value in a new array. If the return value is already an array it basically creates a shallow copy, but if it’s a single object it will be bundled onto an array.

CodePudding user response:

In this case, you can use the @() array subexpression operator or the unary comma operator to force the variable into an array:

myArray1 = @($myFirstArray)
myArray2 = @($mySecondArray)

or

myArray1 = ,$myFirstArray
myArray2 = ,$mySecondArray

Note that you still will lose the [] if you pipe the $MyBigObject through to the ConvertTo-Json cmdlet. Using -InputObject (as you implicitely do) is the correct way here.

  • Related