如何在PowerShell中遍历JSON数据结构?

2024-09-26 20:16:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我是PowerShell的新手,从Python背景中动态学习它

我正在从另一个工具中提取数据,该工具通过REST调用检索数据

METERS变量以这种格式存储在源中

{
    "500 HR": 500,
    "1000 HR": 1000,
    "2000 HR": 2000
}

PowerShell代码

#REST call to source
$meter=@{}
Foreach ($item in $origresult.Items)  {
$result = (Invoke-RestMethod -Uri $url  -Headers $headers -Method GET -ContentType application/json -ErrorVariable RespErr)
$meter.Add($item.Name,$result.Value)
}
Write-Host ($meter | Out-String) -ForegroundColor Red

这是输出

Name                           Value
----                           -----
LastUploaded                   2020-12-29T06:38:02
IsEnabled                      1       
METERS                         {...
ORGID                          WHS

如何检索仪表并遍历字典?我已经试过了。Python以其简单的数据结构宠坏了我,除非有更简单的方法,否则PowerShell就不是那么简单了

$mymeters = $meter.METERS | ConvertFrom-Json
Write-Host ($mymeters | Out-String) -ForegroundColor Yellow

输出

500 HR   : 500
1000 HR  : 1000
2000 HR  : 2000

以下是我迄今为止尝试过的一些东西-

$mymeters = [ordered]@{}
" Here is the item $mymeters.Get_Item(500 HR)" #my silly attempt!
# Looping is a no go either - it says specialized ordered dictionary
foreach ($ind in $mymeters) {
" --> $ind"
}

输出

 Here is the item System.Collections.Specialized.OrderedDictionary.Get_Item(500 HR)
 --> System.Collections.Specialized.OrderedDictionary

我可能错过了一些真正基本的东西,但我自己却无法解决!非常感谢您的帮助。我只想遍历METERS哈希表/字典并调用一个函数


Tags: 工具数据nameinrestisvaluehr
2条回答

在深入研究它之前,让我们先回顾一下PowerShell的一些语法基础知识,看看是否可以重复使用您的一些Python直觉:)

成员访问

就像在Python中一样,您可以使用.成员访问操作符通过name引用对象的属性-对于非连续名称,请使用引号:

$mymeters = $meter.METERS | ConvertFrom-Json
$mymeters.'500 HR'  # evaluates to `500`

字符串表达式

PowerShell中的字符串文字有两种不同的风格:

  • 单引号字符串('Hello World!'
    • 这些是逐字字符串文字,唯一支持的转义序列是''(文字单引号)
  • 双引号字符串("Hello World!"
    • 这些是可扩展的字符串文本-除非显式转义-`是转义字符,否则将自动插入$variable标记和$()子表达式,并且大多数C类语言中的常见序列(`n`t`r等)都是本机识别的

但是,任意表达式(如$dictionary.get_Item('some key'))将不会按原样进行计算

为了解决这个问题,我们可以使用-f字符串格式操作符:

$mymeters = [ordered]@{}
"Here is item '500 HR': {0}" -f $mymeters['500 HR']

如果您习惯于Python3的f字符串,那么-f应该会觉得很熟悉,但有一点需要注意的是,PowerShell的-f操作符是^{}的薄型包装,并且String.Format()只支持基于0的占位符-'{0} {1}' -f 1,2是有效的,而'{} {}' -f 1,2不是

另一个选项是将表达式包装在双引号字符串文字中的$()子表达式运算符中:

$mymeters = [ordered]@{}
"Here is item '500 HR': $($mymeters['500 HR'])"

请注意,PowerShell中的字典支持使用[]键控索引访问,就像Python一样:)


与Python不同的是,PowerShell(以及.NET)也具有强大的内省功能

动态发现和迭代任何对象的属性就像引用名为psobject的特殊成员一样简单:

foreach($propertyMetadataEntry in $someObject.psobject.Properties){
    "Property: {0,-20} = {1}" -f $propertyMetadataEntry.Name,$propertyMetadataEntry.Value
}

或者在您的情况下:

$mymeters = $meter.METERS | ConvertFrom-Json
foreach($meterReading in $mymeters.psobject.Properties){
    "Meter: {0,-20} = {1}" -f $meterReading.Name,$meterReading.Value

    # do whatever else you please with $meterReading here :)
}

这将适用于任何标量对象(如ConvertFrom-JsonInvoke-RestMethod返回的对象)

要迭代字典中的条目,需要显式调用^{

$dictionary = [ordered]@{ A = 1; B = 2; C =3 }
foreach($keyValuePair in $dictionary.GetEnumerator()){
    "Dictionary Entry: {0} = {1}" -f $keyValuePair.Key,$keyValuePair.Value
}

请在下面核对我的答案:

1.)我在powershell 5.x上测试了这些东西。较新或较旧版本的powershell(尤其是较旧版本)的工作原理可能略有不同

2.)Invoke Restmethod会自动将json响应转换为powershell对象,因此无需进一步处理。将所有赋值都放到哈希表中

$responseJson = '{
    "500 HR": 500,
    "1000 HR": 1000,
    "2000 HR": 2000
}'

$response = $responseJson | ConvertFrom-Json

$nodes = (Get-Member -inputobject $response  -MemberType NoteProperty).Name

$nodes | ForEach-Object {
    echo ("Element: $_ Result: " +$response.$_)
    
}

echo "Another one"

#alternative
foreach ($node in $nodes) {
    echo ("Element: $node Result: " +$response.$node)
}

3.)我认为响应的格式不好,因此,如果您可以控制restservice,我建议如下:

$responseJson = '{
    "hr": [
     500,
    1000,
    2000
    ]
}'

$response = $responseJson | ConvertFrom-Json

$response.hr | ForEach-Object {
    echo ("Element: $_ Result: " +$response.$_)
    
}

相关问题 更多 >

    热门问题