代码之家  ›  专栏  ›  技术社区  ›  ThinkCode

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

  •  0
  • ThinkCode  · 技术社区  · 5 年前

    我是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
    

    如何检索METERS并遍历字典?到目前为止,我已经试过了。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哈希表/字典并调用一个函数。

    0 回复  |  直到 5 年前
        1
  •  3
  •   Mathias R. Jessen    5 年前

    在深入了解它之前,让我们回顾一下PowerShell的一些语法基础知识,看看我们是否可以重用你的一些Python直觉:)

    会员访问权限

    就像在Python中一样,你可以通过以下方式引用对象的属性 名称 使用 . 成员访问运算符-对于不连续的名称,请使用引号:

    $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']
    

    f 如果你习惯了Python3的 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 :)
    }
    

    这将适用于任何 标量 object(类似于返回的对象 ConvertFrom-Json Invoke-RestMethod ).

    用于迭代a中的条目 词典 ,您需要显式调用 .GetEnumerator() :

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

    请检查下面的答案:

    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.$_)
        
    }