代码之家  ›  专栏  ›  技术社区  ›  Voo

转换与JSON的不同评估

  •  2
  • Voo  · 技术社区  · 6 年前

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

    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被调用为每个元素。

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

    1 回复  |  直到 6 年前
        1
  •  2
  •   mklement0    6 年前

    ConvertFrom-Json 与大多数其他Cmdlet不同,将数组输出为 单个对象 而不是通过管道逐个发送对象。 〔1〕

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

    相比之下, 将命令封闭在 (...) 把它变成 表达 ,并在管道中使用表达式隐式导致 枚举 表达式结果的 使对象逐个发送。

    因此,你 第二 司令部 % ( 前置对象 )调用脚本块 两次 美元 绑定到 单一对象 每一个。

    简化示例:

    # 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 问题。