【问题标题】:Powershell - Enumeration through multi tiered JSON output using INVOKE-RESTMETHODPowershell - 使用 INVOKE-RESTMETHOD 通过多层 JSON 输出进行枚举
【发布时间】:2018-06-19 07:30:06
【问题描述】:

我正在尝试从其他 API 的一些多层 JSON 输出中返回某个值,但似乎无法正确使用返回的输出,尤其是当您不知道该输出中可能包含什么时(大多数我看到的关于这个假设的示例,您已经知道返回的字段并且可以硬编码这些字段,但在这种情况下不是)。

有问题的 API 是 F5 Local Traffic Manager Rest API...

返回的 JSON 如下所示。我希望从中获得 serverside.curConns 的价值...

{
      "generation": 263285,
      "kind": "tm:ltm:pool:members:membersstats",
      "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
      "entries": {
        "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats": {
          "nestedStats": {
            "kind": "tm:ltm:pool:members:membersstats",
            "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
            "entries": {
              "serverside.curConns": {
                "value": 0
              }
          }
        }
      }
    }
    }

我的问题是,上面的第一个“条目”容器会在我运行它的每台服务器上发生变化,这就是我试图编写的代码,但到目前为止还没有成功。

我的 Powershell 脚本目前看起来像这样...

$f5partition = "Production"
# ======= CHANGE PER ENVIRONMENT ==========
$f5poolname = "Frontend_App_pool"
$f5port = 8080
$user = "myf5userid"
$pass = "myf5password"
$f5server = "myf5server.mydomain.local"
# ======= NO CHANGES BELOW THIS LINE! =======
$servername = $env:COMPUTERNAME
# ====== AUTHORISATION SECTION ==========
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
    Authorization = $basicAuthValue
}
#=== CONNECT TO F5 API =========
$reply = Invoke-RestMethod -Uri https://${f5server}/mgmt/tm/ltm/pool/~${f5partition}~${f5poolname}/members/~${f5partition}~${servername}:${f5port}/stats/?$select=serverside.curConns -Headers $Headers

当我第一次运行它时,有可能(使用 Powershell 的 ISE)通过选项卡浏览 $reply 的结果,所以我最终得到了预期的 0 值...

Write-Host $reply.entries.'https://localhost/mgmt/tm/ltm/pool/~Production~Frontend-App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats'.nestedStats.entries.'serverside.curConns'.value

这很棒。但是对于服务器 PROD_SERVER01。例如,我无法保存该脚本并针对 PROD_SERVER02 运行它,因为它现在在脚本中进行了硬编码。

我真正需要的是 $reply.entries.*.nestedStats.entries.'serverside.curConns'.value 之类的东西,或者我可以通过某种方式询问和处理返回的 JSON 值,这些值不是以任何方式预先确定的。

在这方面收到任何帮助,谢谢

我正在尝试编写一个脚本,该脚本没有需要复制到其他服务器才能运行的包或工具,例如模块或其他 .exe。而这个 Invoke-RestMethod 几乎是在做我想做的事,但是当它使用一个不期望的字段时,我正在努力枚举输出。

谢谢

【问题讨论】:

    标签: powershell


    【解决方案1】:

    在这种情况下,您可以将 JSON 转换为 XML 并使用 XPath 来获取您需要的内容。经过测试和工作:

    # question's original JSON sample above
    $json = ConvertFrom-Json $s;
    
    # change -depth to suit your needs
    $xml = ConvertTo-Xml -NoTypeInformation $json -Depth 10;
    # if you want to take a look at JSON => XML.
    # pretty-print only works in PowerShell console, not ISE
    $xml.Save([Console]::Out);
    
    # 0, what you're looking for....
    $wanted = $xml.DocumentElement.SelectSingleNode(
                  '//Property[@Name="serverside.curConns"]'
              ).FirstChild.InnerText;
    

    恕我直言,使用 PowerShell 解析 JSON 很痛苦/严重缺乏 - 应该有内置支持来解析嵌套的 JSON 对象。

    【讨论】:

    • 太棒了,谢谢。我同意你在 Powershell/JSON 方面的观点,它显然是缺乏的。我确实认为这是不可能的,将其转换为 XML 进行导航可以通过某种方式来证明这一点。当您认为 Microsoft Azure 使用 JSON 和 Powershell 进行服务供应时,这真是太棒了!
    【解决方案2】:

    神奇之处在于使用 $yourObject.psobject

    $json = @"
    {
          "generation": 263285,
          "kind": "tm:ltm:pool:members:membersstats",
          "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
          "entries": {
            "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats": {
              "nestedStats": {
                "kind": "tm:ltm:pool:members:membersstats",
                "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Production~Frontend_App_pool/members/~Production~PROD_SERVER01:8080/~Production~PROD_SERVER01:8080/stats?ver=12.1.3",
                "entries": {
                  "serverside.curConns": {
                    "value": 0
                  }
              }
            }
          }
        }
        }
    "@ | ConvertFrom-Json
    
    $entryName = $json.entries.psobject.Properties.Name
    
    $json.entries.$($entryName).nestedStats.entries.'serverside.curConns'.value
    

    【讨论】:

      猜你喜欢
      • 2015-06-20
      • 2019-01-09
      • 1970-01-01
      • 2015-02-04
      • 1970-01-01
      • 2019-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多