请考虑以下代码:
$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
具体?喜欢错误/问题?
关于管道项目的解包只有一条规则:写入管道的所有数组和集合总是被解包到项目("向下解包一层"或"以非递归方式解包"会更正确的说法,但为了简单起见,到目前为止我们不打算考虑嵌套数组(。
仍然有可能通过使用一元逗号运算符来覆盖此行为:
$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