powershell - Powershell - 使用 INVOKE-RESTMETHOD 通过多层 JSON 输出进行枚举
问题描述
我正在尝试从其他 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 几乎是在做我想做的事,但是当它使用一个不期望的字段时,我正在努力枚举输出。
谢谢
解决方案
在这种情况下,您可以将 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 对象。
推荐阅读
- cython - 如何在 c extern cython 中调用 python 函数?
- scala - 由于 Jedis Pool,Spark 程序卡住了
- c# - 我正在尝试统一制作一个基本的运动脚本,但不断出现错误
- python - 将嵌套列表转换为嵌套字典
- google-custom-search - 所有搜索查询的促销 - Google 自定义搜索
- python - 如何显示“已登录”用户的收藏夹列表
- android - Android改造标头内容待添加
- android - 设备无法识别 Telegram 应用程序
- python - 检查数组元素是否按索引存在并删除重复项
- python - 替代挂钟时间