我有一个JSON对象数组,我想为每个存在的对象添加一个特定的属性.
例如,数组如下:
[
{
"Average": 1.3085,
"ExtendedStatistics": {
},
"Maximum": 0,
"Minimum": 0,
"SampleCount": 0,
"Sum": 0,
"Timestamp": "\/Date(1496972280000)\/",
"Unit": {
"Value": "Percent"
}
},
{
"Average": 1.4324999999999999,
"ExtendedStatistics": {
},
"Maximum": 0,
"Minimum": 0,
"SampleCount": 0,
"Sum": 0,
"Timestamp": "\/Date(1496944680000)\/",
"Unit": {
"Value": "Percent"
}
}
]
Run Code Online (Sandbox Code Playgroud)
我想为所有对象添加"source":"CPU".我该怎么做呢?我是PowerShell的新手并且无法完成这项工作.
您可以执行以下操作:
$JSON | ConvertFrom-Json | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name 'Source' -Value 'CPU' -PassThru
} | ConvertTo-Json
Run Code Online (Sandbox Code Playgroud)
这假设您的JSON输入位于名为的变量中$JSON,您需要将其替换为您访问JSON内容(例如Get-Content yourfile.json).
获得JSON后,我们ConvertFrom-JSON将其转换为PowerShell对象.
然后,我们使用管道将其发送到一个ForEach-Object循环,该循环使用Add-Membercmdlet将属性添加到集合中的每个项目(当前项表示为$_),名为"Source",值为"CPU".根据mklement0的注释,有必要使用-PassThru开关将结果发送回管道.
然后我们将该输出传递给ConvertTo-JSON以将其转换回来.
Mark Wragg的有用答案很有效,但您可能想知道为什么Add-Membercmdlet不能直接用管道传输,而不是需要封闭ForEach-Object调用:
可以说,以下应该可以工作,但目前(Windows PowerShell v5.1,PowerShell Core v6.1.0)不能:
# !! Currently does NOT work as expected.
$JSON | ConvertFrom-Json |
Add-Member -MemberType NoteProperty -Name 'Source' -Value 'CPU' -PassThru
Run Code Online (Sandbox Code Playgroud)
这个想法是Add-Member直接使用管道输入,并且在修改每个输入对象之后输出它,这要归功于-PassThru(默认情况下不Add-Member产生输出).
它不起作用的原因是当ConvertFrom-Json输出数组时,它将其作为单个对象输出,而不是像人们期望的那样通过管道逐个发送它的元素.
PowerShell GitHub存储库中的一个问题正在讨论这种有问题的行为.
如果您同意这是有问题的,请在那里听到您的声音; 甚至一个简单的"竖起大拇指"表明有兴趣改变它.
解决方法:
(...),强制枚举数组:# Enclosing the ConvertFrom-Json command in (...) forces enumeration.
($JSON | ConvertFrom-Json) |
Add-Member -MemberType NoteProperty -Name 'Source' -Value 'CPU' -PassThru
Run Code Online (Sandbox Code Playgroud)
请注意,通常,使用(...)强制在数组中收集命令的整个输出内存是很方便的,但是对于大输出集可能会有问题.然而,正如PetSerAl指出的那样,在这种情况下它很好,因为ConvertFrom-Json它本身无论如何都会在内存中构建整个输出数组.
Write-Output -NoEnumerate(Windows PowerShell)/ Write-Output(PowerShell Core)的传递调用
,其唯一目的是强制枚举数组元素:# Inserting Write-Output [-NoEnumerate] between ConvertFrom-Json and Add-Member
# forces enumeration of the array elements.
# *Windows PowerShell*, as of v5.1:
$JSON | ConvertFrom-Json | Write-Output -NoEnumerate |
Add-Member -MemberType NoteProperty -Name 'Source' -Value 'CPU' -PassThru
# PowerShell *Core*:
$JSON | ConvertFrom-Json | Write-Output |
Add-Member -MemberType NoteProperty -Name 'Source' -Value 'CPU' -PassThru
Run Code Online (Sandbox Code Playgroud)
Write-Output:Windows PowerShell从v5.1开始:
由于一个错误,Write-Output 总是列举单个对象是集合本身,甚至当你添加-NoEnumerate.
矛盾的-NoEnumerate是,在这种情况下实际上需要 - 即使我们确实想要枚举!- 以防止两次Write-Output应用枚举:一次(总是)到输入数组,再次到各个数组元素(再次感谢PetSerAl); 例如:
# !! Unexpectedly returns 4(!): enumerates the outer 2-element array
# !! *and* its elements.
# (In PowerShell *Core*, this yields 2, as expected.)
Write-Output -InputObject (1, 2), (3, 4) | Measure-Object
# BETTER: yields 2, because only the outer 2-element array is enumerated
# (In PowerShell *Core*, this yields 1, as expected.)
Write-Output -NoEnumerate -InputObject (1, 2), (3, 4) | Measure-Object
Run Code Online (Sandbox Code Playgroud)
PowerShell 核心:
上面的问题已得到修复,这意味着 - 明智地 - 如果你想要枚举本身就是集合的管道对象(并且枚举不再递归1级),你就不能使用-NoEnumerate它Write-Output.
不幸的是,引入了一个新的错误:单个标量输入对象意外地包装在一个[PSObject[]]数组中:
> (1 | Write-Output -NoEnumerate).GetType().Name
PSObject[]
Run Code Online (Sandbox Code Playgroud)
PetSerAl 在这里报告了这个错误.
| 归档时间: |
|
| 查看次数: |
3438 次 |
| 最近记录: |