Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the rules for automatic arrays wrapping/unwrapping?

Tags:

powershell

Consider this code:

$a = '[{"a":"b"},{"c":"d"}]'
"Test1"
$a | ConvertFrom-Json | ForEach-Object { $_.GetType() }
"Test2"
$b = $a | ConvertFrom-Json
$b | ForEach-Object { $_.GetType() }

This produces the following output:

Test1

IsPublic IsSerial Name                                     BaseType                                                                                                                           
-------- -------- ----                                     --------                                                                                                                           
True     True     Object[]                                 System.Array                                                                                                                       
Test2
True     False    PSCustomObject                           System.Object                                                                                                                      
True     False    PSCustomObject                           System.Object  

Evidently, if we use a temporary variable, whatever is passed down the pipeline is not the same thing that is passed if we do not use one.

I would like to know what the rules that powershell uses for automatic array wrapping / unwrapping are, and if the using a temp var the best course of action if we need to iterate through a json array.

Update 1 Logically ConvertFrom-Json should return an array with the input given and ForEach-Object should iterated on the said array. However in the first test this does not happen. Why? Update 2 Is it possible that it's ConvertFrom-Json specific? Like bug/issue?

like image 770
Andrew Savinykh Avatar asked Aug 17 '17 00:08

Andrew Savinykh


1 Answers

There is only one rule with regard to pipeline items' unwrapping: all arrays and collections written to the pipeline are always getting unwrapped to the items ("unwrapped one level down" or "unwrapped in a non-recursive fashion" would be more correct statement but for the sake of simplicity we are not going to consider nested arrays so far).

There is still a possibility to override this behavior by using unary comma operator:

$a = 1,2
$a | ForEach-Object{ $_.GetType() }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType
True     True     Int32                                    System.ValueType

,$a | ForEach-Object{ $_.GetType() }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

In the second case Powershell pipeline engine unwrapped $a but afterwards the result got wrapped back to array by , operator.

As to ConvertFrom-Json case I personally believe that its observed behavior is more predictable as it allows you to capture JSON arrays as a whole by default. If you are interested in the details, the function Get-WrappedArray in the code below imitates ConvertFrom-Json's behavior:

function Get-WrappedArray {
  Begin   { $result = @() } 
  Process { $result += $_ } 
  End     { ,$result }
}

$a | Get-WrappedArray | ForEach-Object{ $_.GetType() }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

$b = $a | Get-WrappedArray
$b | ForEach-Object{ $_.GetType() }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType
True     True     Int32                                    System.ValueType
like image 82
maoizm Avatar answered Oct 15 '22 00:10

maoizm