cri*_*ret 7 select json nested object jq
我正在寻找有效的方法来搜索与过滤器匹配的“子对象”的大型 JSON 对象(select()我想是通过)。然而,顶级 JSON 是一个包含任意嵌套的对象,包括更简单的值、对象和对象数组。例如:
{
"name": "foo",
"class": "system",
"description": "top-level-thing",
"configuration": {
"status": "normal",
"uuid": "id"
},
"children": [
{
"id": "c1",
"class": "c1",
"children": [
{
"id": "c1.1",
"class": "c1.1"
},
{
"id": "c1.1",
"class": "FINDME"
}
]
},
{
"id": "c2",
"class": "FINDME"
}
],
"thing": {
"id": "c3",
"class": "FINDME"
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个解决方案,它确实的一部分我想要的(并且是可以理解的):
jq -r '.. | arrays | .[] | select(.class=="FINDME"?) | .id'
Run Code Online (Sandbox Code Playgroud)
返回:
c2
c1.1
Run Code Online (Sandbox Code Playgroud)
...然而,它错过了c3,而且它改变了项目输出的顺序。此外,我希望这可以在可能非常大的 JSON 结构上运行,我想确保找到一个有效的解决方案。jq新手(包括我自己)仍然可以阅读的内容的奖励积分。
FWIW,我在途中用来帮助我的参考资料,以防他们帮助他人:
对于小型到中等大小的 JSON 输入,您处于正确的轨道上..
,但似乎您想要选择objects,如下所示:
.. | objects | select(.class=="FINDME"?) | .id
Run Code Online (Sandbox Code Playgroud)
对于非常大的 JSON 文档,这可能需要太多内存,因此可能值得了解 jq 的流解析器。不幸的是,它使用起来要困难得多,所以我建议尝试上述方法,如果您感兴趣,请在通常的地方查找有关该--stream选项的文档。
这是一个流解析器解决方案。为了理解它,您需要阅读该--stream选项,但关键是输出包含以下形式的行:[PATH, VALUE]
foreach inputs as $in (null;
if has("id") and has("class") then null
else . as $x
| $in
| if length != 2 then null
elif .[0][-1] == "id" then ($x + {id: .[-1]})
elif .[0][-1] == "class"
and .[-1] == "FINDME" then ($x + {class: .[-1]})
else $x
end
end;
select(has("id") and has("class")) | .id )
Run Code Online (Sandbox Code Playgroud)
jq -n --stream -f program.jq input.json
Run Code Online (Sandbox Code Playgroud)
"c1.1"
"c2"
"c3"
Run Code Online (Sandbox Code Playgroud)