我正在尝试使用Powershell访问JSON对象的特定属性值。不幸的是,我不知道结构中某些父级属性的键,因此我无法直接做到这一点。另外,由于JSON不是数组,因此无法通过索引位置访问。
上下文是我正在从elasticsearch查询正在运行的任务列表,并且需要获取任务的ID(我知道只有一个),因此我可以进行后续调用以发现其完成状态。
我已经研究了一些查询方法,但是不确定如何应用它们(PowerShell语法对我来说是很新的)。
我正在使用的JSON响应如下所示;
"nodes" : { "oTUltX4IQMOUUVeiohTt8A" : { "name" : "H5dfFeA", "transport_address" : "127.0.0.1:9300", "host" : "127.0.0.1", "ip" : "127.0.0.1:9300", "tasks" : { "oTUltX4IQMOUUVeiohTt8A:124" : { "node" : "oTUltX4IQMOUUVeiohTt8A", "id" : 124, "type" : "direct", "action" : "cluster:monitor/tasks/lists[n]", "start_time_in_millis" : 1458585884904, "running_time_in_nanos" : 47402, "cancellable" : false, "parent_task_id" : "oTUltX4IQMOUUVeiohTt8A:123" } } } } }
有了这个给定的结构,我希望能够访问第一个“任务”的ID属性。
因此,如果我知道prop键,它将是:
nodes.oTUltX4IQMOUUVeiohTt8A.tasks.oTUltX4IQMOUUVeiohTt8A:124.id
如何在不事先知道密钥的情况下访问此值?
任何帮助非常感谢。
谢谢尼克
以下代码定义并使用 functionGet-FirstPropertyValue,该 函数 对具有给定名称的对象图内的第一个属性 执行 深度优先 的 递归搜索 ,并假设其值为非null:
Get-FirstPropertyValue
# Function that returns the value of the first property with the given # name found during recursive depth-first traversal of the given object. # Note that null-valued properties are ignored. function Get-FirstPropertyValue($obj, $propName) { $propNames = $obj.psobject.properties.Name if ($propName -in $propNames) { $obj.$propName } else { foreach ($iterPropName in $propNames) { if ($null -ne ($val = Get-FirstPropertyValue $obj.$iterPropName $propName)) { return $val } } } } # Input JSON $json = @' { "nodes": { "oTUltX4IQMOUUVeiohTt8A": { "name": "H5dfFeA", "transport_address": "127.0.0.1:9300", "host": "127.0.0.1", "ip": "127.0.0.1:9300", "tasks": { "oTUltX4IQMOUUVeiohTt8A:124": { "node": "oTUltX4IQMOUUVeiohTt8A", "id": 124, "type": "direct", "action": "cluster:monitor/tasks/lists[n]", "start_time_in_millis": 1458585884904, "running_time_in_nanos": 47402, "cancellable": false, "parent_task_id": "oTUltX4IQMOUUVeiohTt8A:123" } } } } } '@ # Convert the JSON to a [pscustomobject] graph with ConvertFrom-Json. $objFromJson = $json | ConvertFrom-Json # Using the function defined above, get the first 'tasks' object found # during recursive depth-first traversal. $tasks = Get-FirstPropertyValue $objFromJson 'tasks' # Get the name of the resulting object's first property. $propName = @($tasks.psobject.properties.Name)[0] # Extract the .id property from the object stored in the first property. $tasks.$propName.id
以上收益:
124
一个 更简洁但更晦涩且可能更慢的替代方法 是 将JSON输入转换为XML,然后使用 XPath对其 进行查询:
# Input JSON $json = @' { "nodes": { "oTUltX4IQMOUUVeiohTt8A": { "name": "H5dfFeA", "transport_address": "127.0.0.1:9300", "host": "127.0.0.1", "ip": "127.0.0.1:9300", "tasks": { "oTUltX4IQMOUUVeiohTt8A:124": { "node": "oTUltX4IQMOUUVeiohTt8A", "id": 124, "type": "direct", "action": "cluster:monitor/tasks/lists[n]", "start_time_in_millis": 1458585884904, "running_time_in_nanos": 47402, "cancellable": false, "parent_task_id": "oTUltX4IQMOUUVeiohTt8A:123" } } } } } '@ $parent = 'tasks' $prop = 'id' $propType = 'int' $json | ConvertFrom-Json | ConvertTo-Xml -Depth ([int]::MaxValue) | Select-Xml "//Property[@Name='$parent']/*/*[@Name='$prop']/text()" | ForEach-Object { $_.Node.InnerText -as $propType }