Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ConvertFrom-Json produce an Object which turns into a PSCustomObject after assignment? And how do I shortcut that?

I have a simple json file as follows:

[
    {"ClientName": "Test Site 1", "ClientID": "000001"},
    {"ClientName": "Test Site 2", "ClientID": "000002"},
    {"ClientName": "Test Site 3", "ClientID": "000003"}
]

When I use the following PowerShell command:

ConvertFrom-Json (Get-Content TestSites.json -Raw)

I get back a System.Object[]. This doesn't allow me to pipe the output to another function I have which accepts "ClientName" and "ClientID" parameters.

However, when I assign that object to another variable, like this:

$myobj = ConvertFrom-Json (Get-Content TestSites.json -Raw)

$myobj is actually a System.Management.Automation.PSCustomObject which is capable of being passed to my function.

How can I just pipe the results of the original command without having to assign it to another variable first?

I hope that makes sense.

like image 318
Darren Avatar asked Oct 15 '25 19:10

Darren


2 Answers

Your JSON is an array correct? PowerShell will unroll arrays in the pipeline unless you explicity change that behavior. Assuming your JSON is stored in the variable $json as a single string consider the following examples.

ConvertFrom-Json $json | ForEach-Object{$_.gettype().fullname}
System.Object[]

(convertFrom-Json $json) | ForEach-Object{$_.gettype().fullname}
System.Management.Automation.PSCustomObject
System.Management.Automation.PSCustomObject
System.Management.Automation.PSCustomObject

You should be able to wrap the expression in brackets to change the outcome. In the second example it should be sending the 3 objects individually down the pipe. In the first it is being sent as a single object array.

My explanation needs work but I am sure of the cause is how PowerShell deals with arrays and the pipeline. Unrolling being a common word used to describe it.

So depending on your use case you might just be able to wrap the expression in brackets so it gets processed before the pipe to ForEach in my example.

like image 194
Matt Avatar answered Oct 18 '25 11:10

Matt


If you have an array such as System.Object[] you could try piping via foreach:

ConvertFrom-Json (Get-Content TestSites.json -Raw) | %{ $_ | your-function }

If you want to pass the whole array down the pipe as-is, you can try adding a comma (aka a unary comma before the variable:

,$myobj | whatever

You can probably see how the latter works by comparing the following:

$myobj | Get-Member            # Shows the type of the elements of the array
Get-Member -InputObject $myobj # Shows the type of the array
,$myobj | Get-Member           # Shows the type of the array
like image 23
Charlie Joynt Avatar answered Oct 18 '25 12:10

Charlie Joynt