对ConvertFrom Json的不同评估



为什么以下两个片段产生不同的输出?

Get-Content -Raw "test.json" | ConvertFrom-Json | %{
Write-Output "MessageType: $($_.Messagetype)"
}
# this time make sure Get-Content and ConvertFrom-Json are evaluated completely, before the foreach
(Get-Content -Raw "test.json" | ConvertFrom-Json) | %{
Write-Output "MessageType: $($_.Messagetype)"
}

使用以下json:执行代码段

[
{
"MessageType": "A"
},
{
"MessageType": "B"
}
]

第一个脚本生成

MessageType: A B

第二个是预期的

MessageType: A
MessageType: B

因此,基本上对于第一个片段,foreach获得一个元素,该元素是一个包含2个元素的数组,而在第二个片段中,foreach为每个元素调用。

我不明白为什么强制评估会完全改变这里的行为。

在v6.x之前的PowerShell版本中,与大多数其他cmdlet不同,ConvertFrom-Json将数组输出为单个对象,而不是通过管道逐个发送对象。

因此,在第一个命令的%(ForEach-Object(脚本块中,$_整个数组,在可扩展字符串("..."(字符串中,默认情况下,它指向由空格分隔的元素列表。

相反,将命令封装在分组运算符()中,会将其转换为表达式,并且在管道中使用表达式会隐式导致表达式结果的枚举,从而导致逐个发送对象。

注意:使用()的另一个显著副作用是,一个封闭的命令的输出被完全收集在内存中。

因此,第二个命令的%(ForEach-Object(脚本块被调用两次$_分别绑定到单个对象

简化示例:

# Sample JSON that is an array comprising 2 objects.
$json = '[
{
"MessageType": "A"
},
{
"MessageType": "B"
}
]'
# PS v6.x-: -> 1, because ConvertFrom-Json sent the array as a whole
$json | ConvertFrom-Json | Measure-Object | % Count
# -> 2, because using (...) resulted in enumeration
($json | ConvertFrom-Json) | Measure-Object | % Count

最新更新