一次将对象数组添加到PSObject

时间:2018-11-30 18:11:13

标签: powershell

我想以编程方式将主服务器和详细信息列表中的json数据连接起来。我的代码的一个简化示例为:

$master = '[{"Sample": 1.3085},{"Sample":  1.4567}]' | ConvertFrom-Json
$detail = '[{"foo":1, "bar":2},{"foo":3, "bar":4}]' | ConvertFrom-Json

$master  | %{ 
    $_ | Add-Member -MemberType NoteProperty -Name 'Detail' -Value $detail -PassThru
} | ConvertTo-Json  

我希望这样:

[{
        "Sample": 1.3085,
        "Detail": [
                {"foo" :1, "bar":2},
                {"foo" :3, "bar":4}
            ]
        }
    }, {
        "Sample": 1.4567,
        "Detail": [
                {"foo" :1, "bar":2},
                {"foo" :3, "bar":4}
            ]
        }
    }
]

但是我明白了

[{
        "Sample": 1.3085,
        "Detail": {
            "value": [
                "@{foo=1; bar=2}",
                "@{foo=3; bar=4}"
            ],
            "Count": 2
        }
    }, {
        "Sample": 1.4567,
        "Detail": {
            "value": [
                "@{foo=1; bar=2}",
                "@{foo=3; bar=4}"
            ],
            "Count": 2
        }
    }
]

在我看来,Add-Member代码段将PSObject值转换为字符串,而不是直接使用它。

另外:当$ master数组仅包含个元素时,虽然效果不如预期,但效果更好,但如果存在多个元素,则字符串化结果会得到 >如上所示。

这是$ master中只有一项的结果:

{
    "Sample":  1.3085,
    "Detail":  {
                   "value":  [
                                 {
                                     "foo":  1,
                                     "bar":  2
                                 },
                                 {
                                     "foo":  3,
                                     "bar":  4
                                 }
                             ],
                   "Count":  2
               }
}

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

您的代码有两个问题:

  • 您遇到的 bug 仍然存在于 Windows PowerShell 中,但是由于已在Powershell Core < / em>,这会导致不需要的valueCount属性出现在数组中-请参见this GitHub issue

  • 为确保将输入对象树的完整深度转换为JSON ,您需要将默认的 -Depth 增加为(至少)与实际深度匹配。 [1]

解决两个问题都会产生:

# Windows PowerShell workaround for array-serialization bug.
# See https://github.com/PowerShell/PowerShell/issues/3222
Remove-TypeData -ErrorAction Ignore System.Array

$master = '[{"Sample": 1.3085},{"Sample":  1.4567}]' | ConvertFrom-Json
$detail = '[{"foo":1, "bar":2},{"foo":3, "bar":4}]' | ConvertFrom-Json

$master | ForEach-Object { 
  $_ | Add-Member -MemberType NoteProperty -Name 'Detail' -Value $detail -PassThru
} | ConvertTo-Json -Depth 3  # Note the required -Depth value.

[1]也许令人惊讶的是,-Depth默认为2,这对于用户来说是一个常见的陷阱-请参阅this question

答案 1 :(得分:0)

好吧,在弄乱了一段时间之后,就可以了。

$master = '[{"Sample":1.3085},{"Sample":1.4567}]'

$detail = '[{"foo":1,"bar":2},{"foo":3,"bar":4}]'

$master = ConvertFrom-Json -InputObject $master
$detail = ConvertFrom-Json -InputObject $detail

$i = 0
$master | % { 

$_ | Add-Member -Name 'Detail' -Value $detail.GetValue($i) -MemberType NoteProperty -PassThru

$i++
} | ConvertTo-Json -Depth 3

将新成员添加到[PSCustomObject]时出现问题,什么也没指定每个值应该去哪里。相反,它只是将所有值附加到新的“详细信息”成员。我能够通过运行一个foreach循环来绕过这个问题,并且每次迭代都将1加到变量$i