对ConvertFrom-Json的不同评估

时间:2018-12-03 21:40:16

标签: powershell

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

Connection

使用以下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)"
}

第一个脚本产生

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

第二个是预期的

MessageType: A B

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

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

1 个答案:

答案 0 :(得分:2)

ConvertFrom-Json与大多数其他cmdlet不同,它将数组作为单个对象 输出,而不是通过管道一一发送对象。 [1 ]

因此,在您的 first 命令的%ForEach-Object)脚本块中,$_ entire数组,可扩展字符串("...")内的字符串会默认为由空格分隔的其元素列表。

相比之下,(...)中加上命令会将其转换为表达式,并且在管道中使用表达式会隐式导致枚举表达式的结果,导致对象被一一发送。

因此,您的 second 命令的%ForEach-Object)脚本块被两次调用,其中$_绑定到< em>单个对象。

简化示例:

# Sample JSON that is an array comprising 2 objects.
$json = '[
  {
    "MessageType": "A"
  },
  {
    "MessageType": "B"
  }
]'

# -> 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

[1]此异常行为在this GitHub问题中进行了讨论。