Powershell: ConvertFrom-Json doesn't unwrap arrays on output, resulting in an extraneous wrapper JSON object with `Count` and `Value` properties on reconversion

Created on 15 Feb 2017  路  8Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

'[ 1, 2 ]' | ConvertFrom-Json | ConvertTo-Json

Expected behavior

[
    1,
    2
]

Actual behavior

{
    "value":  [
                  1,
                  2
              ],
    "Count":  2
}

I believe the root cause is that ConvertFrom-Json sends arrays _as a whole_ through the pipeline instead of unwrapping them.

Analysis, more examples, and workaround here: http://stackoverflow.com/a/38212718/45375

Environment data

PowerShell v6.0.0-alpha (v6.0.0-alpha.15) on Darwin Kernel Version 16.4.0: Thu Dec 22 22:53:21 PST 2016; root:xnu-3789.41.3~3/RELEASE_X86_64
PowerShell v5.1.14393.693 on Microsoft Windows 10 Pro (64-bit; v10.0.14393)
Area-Cmdlets-Utility Resolution-Fixed

Most helpful comment

@JohnLBevan: Let's continue the conversation at #3424, which is still open (and where you've previously commented too ).

In short, my suggestion is to make ConvertFrom-Json's behavior PowerShell-friendly _by default_ (by _unwrapping, as usual_), while giving users the ability to opt into array-as-single-output-object behavior with -NoEnumerate, if needed.

Thus, the above example would become:

'[ 1 ]' | ConvertFrom-Json -NoEnumerate | ConvertTo-Json

All 8 comments

Workaround: Remove-TypeData -TypeName System.Array.

Fixed in alpha.17 via #3231

@SteveL-MSFT: The example in this bug report now works as intended in alpha.17, but ConvertFrom-Json still unexpectedly sends an output array _as a whole_ through the pipeline:

> '[ 1, 2 ]' | ConvertFrom-Json | % GetType | % Name
Object[]

Contrast this with a regular array:

> 1, 2 | % GetType | % Name
Int32
Int32

@mklement0 can you open a new issue? thanks!

@mklement0
Should

'[ 1 ]' | ConvertFrom-Json | ConvertTo-Json

return [ 1 ]?

@PetSerAl: It's a fair point - if you unwrap the array, information is lost.

But that equally applies to:

, 1 | ForEach-Object { $_ }  # or even:  , 1 | ForEach-Object { , $_ }

So it's weighing PowerShell's normal collection handling against preserving information about the input.

Perhaps if no one ever notices _in practice_ that the collection is passed _as a whole_, the alpha.17 behavior is fine.

Not sure what the right answer is.

@SteveL-MSFT: Thanks; I will, once I have clarity over whether that's indeed a problem.

NB: Noticed this in practice... passing the output of ConvertFrom-Json down the pipeline to a function with arguments ValueFromPipelineByPropertyName gives error The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

@PetSerAl's comment is valid though; so perhaps a switch is required -UnwrapCollection to select preferred behaviour at runtime?

@JohnLBevan: Let's continue the conversation at #3424, which is still open (and where you've previously commented too ).

In short, my suggestion is to make ConvertFrom-Json's behavior PowerShell-friendly _by default_ (by _unwrapping, as usual_), while giving users the ability to opt into array-as-single-output-object behavior with -NoEnumerate, if needed.

Thus, the above example would become:

'[ 1 ]' | ConvertFrom-Json -NoEnumerate | ConvertTo-Json
Was this page helpful?
0 / 5 - 0 ratings