Skip to content

ConvertFrom-Json and ConvertTo-Json eat the one object array #2448

Closed

Description

@SummerSun

OS info

Edition: Windows 10 Enterprise
Version: 1607
OS Build: 14393.187
Installed RAM: 16.0 GB
System Type: 64-bit operating system, x64-based processor

Steps to reproduce

  1. Create a .json file. Write in an array with only one valid json object:
[{
    "name": "Animals",
    "age": "1",
    "children": [{
        "name": "mimi",
        "age": "1",
        "lovely": true,
        "height": 20
    },
    {
        "name": "dog",
        "age": "2",
        "lovely": false,
        "height": 100
    }]
}]
  1. Convert this json file content to psobject and then convert it back to write it to another file
$o=(Get-Content -Raw D:\Test_Convert.json | ConvertFrom-Json)
Set-Content 'D:\result.json' ($o | ConvertTo-Json)
  1. View the result.json:
{
    "name":  "Animals",
    "age":  "1",
    "children":  [
                     {
                         "name":  "mimi",
                         "age":  "1",
                         "lovely":  true,
                         "height":  20
                     },
                     {
                         "name":  "dog",
                         "age":  "2",
                         "lovely":  false,
                         "height":  100
                     }
                 ]
}

Expected behavior

Get the right PSObject and write the same content back.

Actual behavior

The array turns into its only child.

Environment data

Included in the repro steps.

Powershell Version

PS C:\Users\qisun\Downloads\LatestPowerShell> $PSVersionTable.PSVersion

Major Minor Patch Label
----- ----- ----- -----
    6     0     0 alpha

Have to mention that the issue does not repro when there are multiple children in that array.

Activity

  1. SteveL-MSFT commented on Oct 12, 2016

    @SteveL-MSFT
    Member

    Francisco Gamino (@Francisco-Gamino) I think you had brought this up before and this was "by design"?

  2. lzybkr commented on Oct 26, 2016

    @lzybkr
    Contributor

    With the repro as is, it does look like it is by design - we enumerate objects written to the pipeline, so piping loses the fact that the object was an array. This is similar to the difference between:

    $o = @(1)
    $o | Get-Member
    Get-Member -InputObject $o

    I was going to suggest using:

    Set-Content 'D:\result.json' (ConvertTo-Json -InputObject $o)

    But this doesn't work either, and I would consider this a bug.

  3. added this to the milestone on Nov 4, 2016
  4. modified the milestones: , on Feb 28, 2017
  5. modified the milestones: 6.0.0-beta1, on Mar 16, 2017
  6. modified the milestones: , on May 15, 2017
  7. kamranayub commented on May 19, 2017

    @kamranayub

    Just ran into this the other day, the workaround I'm using is

    Set-Content 'D:\result.json' (ConvertTo-Json -InputObject @($o))
    

    The fact that it still won't work in pipeline is annoying. I have a restriction that I have to use pipeline, so I end up doing:

     .\Some-Script.ps1 -OutVariable List | Out-Null; ConvertTo-Json -InputObject @($List)
    

    And that works. I'm restricted because in this context, the script reference must be first and all other arguments are appended afterwards. I almost want a -AsArray switch or something to ConvertTo-Json.

    .\Some-Script.ps1 | ConvertTo-Json -AsArray
    
  8. Francisco-Gamino commented on May 19, 2017

    @Francisco-Gamino
    Contributor

    The pipleline issue is by design; however, this is not documented, so I've create an doc issue for this: MicrosoftDocs/PowerShell-Docs#1219

    For the ConvertTo-Json -InputObject $array, I cannot get it to repro. Here is what I am running:

    # Generate a test file with Json content
    '[{
        "name": "Animals",
        "age": "1",
        "children": [{
            "name": "mimi",
            "age": "1",
            "lovely": true,
            "height": 20
        },
        {
            "name": "dog",
            "age": "2",
            "lovely": false,
            "height": 100
        }]
    }]'  | Out-File Test_Convert.json
    
    # Create the test object from the Json file
    $o=(Get-Content -Raw Test_Convert.json | ConvertFrom-Json)
    $o
    
    name    age children
    ----    --- --------
    Animals 1   {@{name=mimi; age=1; lovely=True; height=20}, @{name=dog; age=2; lovely=False; height=100}}
    
    # Serialize the object using  ConvertTo-Json -InputObject
    Set-Content result.json (ConvertTo-Json -InputObject $o -Depth 3)
    
    Get-Content .\result.json
    [
      {
        "name": "Animals",
        "age": "1",
        "children": [
          {
            "name": "mimi",
            "age": "1",
            "lovely": true,
            "height": 20
          },
          {
            "name": "dog",
            "age": "2",
            "lovely": false,
            "height": 100
          }
        ]
      }
    ]
    

    Since the pipleline issue is by design, I am closing this. Please reopen is ConvertTo-Json -InputObject $array does not work.

  9. gramae commented on Jan 7, 2018

    @gramae

    In my case this approach adds "value": at the beggining and "Count": 1 at the end:

    {
    "value": [
    {
    "name": "Animals",
    "age": "1",
    "children": [
    {
    "name": "mimi",
    "age": "1",
    "lovely": true,
    "height": 20
    },
    {
    "name": "dog",
    "age": "2",
    "lovely": false,
    "height": 100
    }
    ]
    }
    ],
    "Count": 1
    }

  10. utripathi commented on Mar 7, 2018

    @utripathi

    Does this support complex json files .

    Referring to the Azure ARM templates which are in the json format .

    Does it support that too ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions