MS PowerShell:如何处理JSON对象?

ms powershell: how to handle json- objects?

提问人:am2 提问时间:11/17/2023 更新时间:11/17/2023 访问量:33

问:

我有一个包含内容的文件

{
  "Names" : {"first" : "Chuck", "second" : "Norris"},
  "Numbers" : {"one" : "1", "two" : "2"}
}

我可以用 ConvertFrom-Json 和 ConvertTo-Json 读/写和转换它,这没问题。我可以把“查克”改成“卡洛斯·雷”。 但是我怎么能

  • 添加一个新的元组,如 f.e.月份(“1st” : “January” ...
  • 在现有元组内添加一行,例如“Numbers” -> “three” : 3
  • 删除行
  • 删除元组

?这意味着:我想读取文件并将其转换为$variable,修改$variable并转换并写入文件。

谢谢

JSON PowerShell

评论


答:

2赞 Santiago Squarzon 11/17/2023 #1
$json = @'
{
  "Names" : {"first" : "Chuck", "second" : "Norris"},
  "Numbers" : {"one" : "1", "two" : "2"}
}
'@ | ConvertFrom-Json

添加一个新的元组,如 f.e.月份(“1st” : “January” ...

$json.PSObject.Properties.Add(
    [psnoteproperty]::new(
        'Months',
        [pscustomobject]@{ '1st' = 'January' }))
$json | ConvertTo-Json

在现有元组内添加一行,例如“Numbers” -> “three” : 3

$json.Numbers.PSObject.Properties.Add(
    [psnoteproperty]::new('three', '3'))
$json | ConvertTo-Json

删除行

从第一个示例中删除添加的属性。Months

$json.PSObject.Properties.Remove('Months')
$json | ConvertTo-Json

删除元组

删除添加的对象。three

$json.Numbers.PSObject.Properties.Remove('three')
$json | ConvertTo-Json
1赞 mklement0 11/17/2023 #2

为了补充 Santiago Squarzon 的有用回答

ConvertFrom-Json 是 PowerShell 的 cmdlet,用于将 JSON 文本分析为对象图

  • Windows PowerShell 中,你总是会得到 [pscustomobject] 图,而 Santiago 的回答向你展示了如何使用这些图。

  • PowerShell (Core) 7+ 中,可以选择使用 -AsHashTable 开关获取(排序)[哈希表]

基于哈希表的对象图通常更轻量级更适合以后的修改,例如在您的案例中:

# PS 7+ ONLY
$fromJson = @'
{
  "Names" : {"first" : "Chuck", "second" : "Norris"},
  "Numbers" : {"one" : "1", "two" : "2"}
}
'@ | ConvertFrom-Json -AsHashtable

# --- UDPATE / ADDITION operations

# Update a nested entry.
$fromJson.Names.first = 'Carlos Ray'

# Add a new top-level entry
$fromJson.Months = [ordered] @{ '1st' = 'January'}

# Add a new nested entry
$fromJson.Numbers.three = 3

# Print the state of the hahstable now.
$fromJson | Out-Host

# --- REMOVAL operations

# Remove a top-level entry
$fromJson.Remove('Names')

# Remove a nested entry
$fromJson.Numbers.Remove('two')

$fromJson | Out-Host

输出:

# After entry updates / additions.
Name                           Value
----                           -----
Names                          {[first, Carlos Ray], [second, Norris]}
Numbers                        {[one, 1], [two, 2], [three, 3]}
Months                         {[1st, January]}


# After entry removals.
Name                           Value
----                           -----
Numbers                        {[one, 1], [three, 3]}
Months                         {[1st, January]}

注意

  • 在 PowerShell 7.3+ 中,返回 [System.Management.Automation.OrderedHashtable] 实例的图形,该实例保留条目定义顺序,就像 PowerShell 的哈希表[1]一样;在 v7.2- 中,它们是常规的 [System.Collections.Hashtable] 实例。-AsHashtable[ordered] @{ ... }

  • 但是,无论哪种方式,为了符合 JSON,ConvertFrom-Json 返回的哈希表在键查找方面区分大小写,这与 PowerShell 的常规哈希表 (, ) 不同。@{ ... }[ordered] @{ ... }

  • 选择是否使用 -AsHashTable

    • 虽然使用哈希表对象图通常是可取的(更轻量级,更易于修改),但在某些情况下,鉴于哈希表和对象不能完全互换,获取图仍然是必须的。[pscustomobject]

    • 相反,如果 JSON 包含的对象的属性名称只是彼此的大小写变体,则必须这样做,因为 PowerShell 中的真实属性访问本质上不区分大小写;例如:-AsHashTable

      # !! FAILS, because a [pscustomobject] instance cannot
      # !! have property names that differ in case only.
      '{ "foo": 1, "FOO": 2 }' | ConvertFrom-Json
      
      # OK - the hashtable returned is case-sensitive.
      '{ "foo": 1, "FOO": 2 }' | ConvertFrom-Json -AsHashTable
      

[1] 这些文本成为 [System.Collections.Specialized.OrderedDictionary] 实例,实际上,OrderedHashtable 实现也在幕后使用,但区分大小写。