自动数组包装/解包的规则是什么?

时间:2017-08-17 00:50:49

标签: powershell

考虑以下代码:

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

这会产生以下输出:

Test1

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

显然,如果我们使用临时变量,那么传递给管道的任何东西与我们不使用它时传递的东西不同。

我想知道powershell用于自动数组包装/解包的规则是什么,如果我们需要遍历json数组,那么使用temp var是最好的操作方法。

更新1 逻辑上ConvertFrom-Json应该返回一个给定输入的数组,ForEach-Object应该在所述数组上迭代。然而,在第一次测试中,这不会发生。为什么? 更新2 它可能是ConvertFrom-Json具体的吗?喜欢bug / issue?

1 个答案:

答案 0 :(得分:0)

关于管道项目的展开只有一个规则:写入管道的所有数组和集合总是被解包到项目(“展开一层”或“以非递归方式解包” “这将是更正确的陈述,但为了简单起见,到目前为止我们不会考虑嵌套数组。”

使用一元逗号运算符仍有可能覆盖此行为:

$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

在第二种情况下,Powershell管道引擎解包$a但后来结果被,运算符包裹回数组。

关于ConvertFrom-Json情况,我个人认为其观察到的行为更具可预测性,因为它允许您默认捕获JSON数组。 如果您对详细信息感兴趣,下面代码中的函数Get-WrappedArray会模仿ConvertFrom-Json的行为:

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