【问题标题】:Powershell Add-Member - But without "Value" and "Count" elements in JSONPowershell Add-Member - 但 JSON 中没有“Value”和“Count”元素
【发布时间】:2019-12-25 19:55:47
【问题描述】:

我成功地向我的 JSON 添加了一个成员,但我最终得到了不需要的元素。我要添加的是结果 JSON 中出现的“值”内的元素。

{
"Block1": value1,
"Block2": value2,
"Block3": []
}

然后执行 Add-Member cmdlet。

$objectFromJson |
  Add-Member -NotePropertyName "Block3" -NotePropertyValue $newblock -Force

我意识到我不必执行 -Force 部分,但在我的工作代码中,我的 JSON 字符串使用 ConvertFrom-Json 解析为一个对象,并且部分对我的目的有效。

$newblock中存储的数组有1到N个元素,要序列化为数组值属性Block3

不幸的是,我最终得到以下结果:

{
"Block1": value1,
"Block2": value2,
"Block3": [ { "value": { <elements of $newblock> }, "Count": <n> } ]
}

在上面的 sn-p 中,&lt;elements of $newblock&gt; 表示 $newblock 数组元素的 JSON 表示,&lt;n&gt; 表示数组中元素的数量。

这是有效的 JSON,但不是我想要的。相反,我希望$newblock 的元素成为Block3 数组的直接元素,而不需要带有valueCount 属性的无关包装对象:

{
"Block1": value1,
"Block2": value2,
"Block3": [ <elements of $newblock> ]
}

【问题讨论】:

    标签: json powershell cmdlet


    【解决方案1】:

    我的问题的解决方法如下(伪代码):

    $json = @"
    {
    "Block1": value1,
    "Block2": value2,
    "Block3": []
    }
    "@
    
    $objFromJson = $json | ConvertFrom-Json
    
    $listCount = ($newblock.ToCharArray() | Where-Object ($_ -eq ";" | Measure-Object).Count + 1
    
    for($i = 0; $i -lt $listCount; $i++) {
      $newJson = @{ element1 = value1; element2 = value2; etc. }
      $objFromJson.Block3 += $newJson
    }
    
    $objFromJson | ConvertTo-Json
    

    我遇到的问题是Add-Member 是错误的方法,因为它在幕后添加了 PSObject 或 PSCustomObject。

    感谢 @mklement0 指出我的问题的根本原因。

    【讨论】:

      【解决方案2】:

      tl;dr

      • Your own solution 避免了最初的问题,并且可以说是更好的开始方法:将.Block3 属性创建为数组通过原始 JSON(而不是稍后通过 @ 987654325@),稍后使用+=向该数组添加元素。

      • 1234563 $newblock 导致问题。继续阅读以获得解释。

      最后重要的是:存储在.Block3属性中的数组不能有不可见的[psobject]包装器,因为Windows PowerShell 中会导致数组序列化为 JSON,该 JSON 包装在具有 "Count""values" 属性额外对象中。

      额外的对象源于存在名为 .Count 的用于数组的过时 ETS(扩展类型系统)属性,该属性对 [psobject] 包装的数组生效 - 有关血腥细节,请参阅 this answer

      PowerShell [Core] v6+ 中不再出现此问题,因为该 ETS 属性已在此处删除。

      Add-Member 是错误的方法,因为它在幕后添加了 PSObject 或 PSCustomObject。

      实际上,Add-Member 本身不会这样做,因为-NotePropertyValue 参数是[object]-typed,而不是[psobject]-typed。

      存储在您的$newblock 变量中的数组必须已经被[psobject] 包装:
      $newblock -is [psobject] 可能为您指示$true,而常规数组则没有(例如,1, 2 -is [psobject] 是@987654346 @)

      例如,从 cmdlet 返回的数组作为一个整体将有一个不可见的 [psobject] 包装器,尤其是当您使用 New-Object cmdlet 时:(New-Object string[] 2) -is [psobject] 返回$true

      请参阅 this GitHub issue,了解添加了这个不可见的额外 [psobject] 包装器的所有场景,这也可能导致其他细微的行为差异,从 v7.0 起仍会影响 PowerShell [Core](但是,如前所述, 特定问题已通过删除 ETS 属性得到解决)。


      有两种一般解决方法

      • 会话范围

        • 在调用 ConvertTo-Json 之前,运行以下命令,删除过时的 ETS 属性,之后数组按预期序列化 - 无论 [psobject]-wrapped 与否:
          Remove-TypeData System.Array
      • 对于给定的数组变量

        • 使用.psobject.BaseObject 访问数组的未包装底层.NET 数组;在你的情况下:$newblock.psobject.BaseObject

      示例:

      会话范围的解决方法:

      # The problem: Serialize a [psobject]-wrapped array (0, 0):
      PS> ConvertTo-Json -InputObject (New-Object int[] 2)
      # Note the extra object with the "count" (element count) and "value" property (elements)
      {
          "value":  [
                        0,
                        0
                    ],
          "Count":  2
      }
      
      # Remove the ETS definitions for System.Array
      Remove-TypeData System.Array
      
      # Rerun the command:
      PS> ConvertTo-Json -InputObject (New-Object int[] 2)
      # OK
      [
          0,
          0
      ]
      

      给定数组变量的解决方法

      PS> $arr = New-Object int[] 2; ConvertTo-Json -InputObject $arr
      # Note the extra object with the "count" (element count) and "value" property (elements)
      {
          "value":  [
                        0,
                        0
                    ],
          "Count":  2
      }
      
      # $arr.psobject.BaseObject bypasses the [psobject] wrapper
      PS> ConvertTo-Json -InputObject $arr.psobject.BaseObject
      # OK
      [
          0,
          0
      ]
      

      【讨论】:

      • 好东西。感谢您的深入分析。我希望我们的努力最终能帮助别人。干杯。
      • 当然帮了我!
      猜你喜欢
      • 1970-01-01
      • 2022-10-18
      • 2021-10-02
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-26
      相关资源
      最近更新 更多