Powershell附加成员-但不包含“值"和“计数" JSON中的元素 [英] Powershell Add-Member - But without "Value" and "Count" elements in JSON

查看:69
本文介绍了Powershell附加成员-但不包含“值"和“计数" JSON中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已成功将成员添加到JSON,但最终得到不需要的元素.我要添加的是出现在结果JSON中的值"中的元素.

I am successfully adding a member to my JSON, but I end up with unwanted elements. What I am trying to add is the element inside "Value" that is appearing in the resulting JSON.

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

然后执行Add-Member cmdlet.

Then doing the Add-Member cmdlet.

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

我意识到我不必做 -Force 部分,但是在我的工作代码中,我的JSON字符串使用 ConvertFrom-Json 解析为一个对象,并且对我而言,这部分有效.

I realize I do not have to do the -Force part, but in my working code, my JSON string is parsed to an object using ConvertFrom-Json and that part is effective for my purposes.

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

There are from 1 to N elements in the array stored in $newblock, to be serialized as array-valued property Block3.

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

Unfortunately, I end up with the following:

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

在上面的代码段中,<elements of $newblock>表示$newblock数组元素的JSON表示形式,以及<n>数组中元素的计数.

In the snippet above, <elements of $newblock> represent the JSON representation of the $newblock array elements, and <n> the count of elements in the array.

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

It is valid JSON, but not what I desire. Instead, I want the elements of $newblock to be direct elements of the Block3 array, without the extraneous wrapper object with the value and Count properties:

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

推荐答案

tl; dr

  • 您自己的解决方案避免了原始问题,并且可以说是更好的入门方法:通过原始JSON (而不是稍后通过Add-Member)将.Block3属性作为数组(而不是稍后通过Add-Member),并在以后使用+=将元素添加到该数组中.

  • Your own solution avoids the original problem, and is arguably the better approach to begin with: Create the .Block3 property as an array via the original JSON (rather than later via Add-Member), and add elements to that array later with +=.

但是,您可以通过简单地(但晦涩地)传递
-NotePropertyValue $newblock.psobject.BaseObject而不是
-NotePropertyValue $newblock来解决原始问题,这将删除存储在数组周围的不可见的[psobject]包装器导致问题的$newblock.继续阅读以获取解释.

However, you could have fixed the original problem by simply (but obscurely) passing
-NotePropertyValue $newblock.psobject.BaseObject instead of
-NotePropertyValue $newblock, which removes the invisible [psobject] wrapper around the array stored in $newblock that caused the problem. Read on for an explanation.

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

What matters in the end is: the array stored in the .Block3 property must not have an invisible [psobject] wrapper, because in Windows PowerShell that causes the array to serialize to JSON wrapped in an extra object with "Count" and "values" properties.

额外的对象源于数组的名为.Count的过时ETS(扩展类型系统)属性的存在,该属性对[psobject]封装的数组生效-请参见

The extra object stem from the presence of an obsolete ETS (extended-type system) property named .Count for arrays, which takes effect for [psobject]-wrapped arrays - see this answer for the gory details.

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

The problem no longer surfaces in PowerShell [Core] v6+, because this ETS property has been removed there.

添加成员是错误的方法,因为它在幕后添加了PSObject或PSCustomObject.

Add-Member was the wrong approach, since it adds a PSObject or PSCustomObject under the covers.

实际上,Add-Member本身不会执行 的操作,因为-NotePropertyValue参数是[object]类型的,而不是[psobject]类型的.

Actually, Add-Member by itself does not do that, because the -NotePropertyValue parameter is [object]-typed, not [psobject]-typed.

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

The array stored in your $newblock variable must already have been [psobject] wrapped:
$newblock -is [psobject] probably indicates $true for you, whereas a regular array does not (e.g., 1, 2 -is [psobject] is $false)

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

For instance, an array returned from a cmdlet, as a whole will have an invisible [psobject] wrapper, notably when you use the New-Object cmdlet:
(New-Object string[] 2) -is [psobject] returns $true

请参见此GitHub问题,以了解所有这种看不见的额外内容[psobject]的情况.添加了包装程序,这也可能导致其他细微的行为差异,这些差异仍会影响v7.0或更高版本的PowerShell [Core](但如上所述,特定问题已通过删除ETS属性).

See this GitHub issue for all scenarios in which this invisible extra [psobject] wrapper is added, which can cause other subtle behavioral differences as well, which still affect PowerShell [Core] as of v7.0 (but, as stated, this particular issue has been fixed by the removal of the ETS property).

有两种一般解决方法:

  • 整个会话:

  • 在调用ConvertTo-Json之前,运行以下命令,该命令将删除过时的ETS属性,此后,数组将按预期的顺序进行序列化-是否包装[psobject]:
    Remove-TypeData System.Array
  • Before calling ConvertTo-Json, run the following command, which removes the obsolete ETS property, after which arrays serialize as expected - whether [psobject]-wrapped or not:
    Remove-TypeData System.Array

对于给定的数组变量:

  • 使用.psobject.BaseObject访问数组的未包装基础.NET数组;您的情况:$newblock.psobject.BaseObject
  • Use .psobject.BaseObject to access the array's unwrapped, underlying .NET array; in your case: $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
]

这篇关于Powershell附加成员-但不包含“值"和“计数" JSON中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆