ConvertFrom-Json unpacks arrays with 1 item and behaves oddly with empty object

175 Views Asked by At

I am trying to figure out how to stop ConvertFrom-Json from unpacking array types if they have one or zero items.

I have read these related posts: ConvertTo-JSON an array with a single item How to prevent ConvertFrom-Json from collapsing nested arrays if there's 1 element

After reading these, I don't think I am experiencing the member access enumeration because I am not using the access operator.

I attempted to use ConvertFrom-Json without the use of pipelining but that didn't fix the issue as it did for someone using ConvertTo-Json

Here is a simple example with output:

$x = '[{"a": 1, "b": 2}]'
$y = ConvertFrom-Json -InputObject $x

$a = '[]'
$b = ConvertFrom-Json -InputObject $a

Write-Host $y -ForegroundColor Green
Write-Host $y.GetType() -ForegroundColor Green

Write-Host $b -ForegroundColor Green
Write-Host $b.GetType() -ForegroundColor Green
@{a=1; b=2} # first object in array, not array
System.Management.Automation.PSCustomObject # treats as object instead of array
# nothing was printed here because b is null
InvalidOperation: C:\Users\username\Test.ps1:11:1 # error from trying to print the type of b
Line |
  11 |  Write-Host $b.GetType() -ForegroundColor Green
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | You cannot call a method on a null-valued expression.

The kind of output I expected was the GetType() calls to return System.Object[]

Additional Context:

I am using the github cli to get lists of PRs for different repos and aggregate some data for some internal workflows. Obviously it is possible for a repo to have 0, 1 or more PRs and I am hoping to avoid any special logic for the 0 or 1 case, as an empty array or array with one item can follow the same code path as an array with many items.

1

There are 1 best solutions below

2
On BEST ANSWER

The behavior you're seeing implies that you're using PowerShell (Core) 7+ rather than Windows PowerShell.

While your command happens to work in Windows PowerShell, it relies on behavior that contravenes the usual pipeline behavior, i.e. enumerating arrays - see the (now closed) GitHub issue #3424 for background information.

It is for this reason that in PowerShell 7+ ConvertFrom-Json now enumerates the elements of a parsed-from-JSON array by default, and requires opt-in in order to request that a such an array be output as a single object, using the -NoEnumerate switch:

$x = '[{"a": 1, "b": 2}]'

# Note the -NoEnumerate switch (v7+)
$y = ConvertFrom-Json -NoEnumerate -InputObject $x

$y.GetType().Name # -> 'Object[]', proving that the array was preserved.