我有带有嵌套对象的JSON
。{
"schema1": {
"table1": {
"status": 0
},
"table2": {
"status": 1
}
},
"schema2": {
"table1": {
"status": 0
},
"table2": {
"status": 1
}
}
}
我需要按状态==1过滤的架构表列表。我的第一个方法是
.[]|.[]|(select(.status==1))|"table.schema (.status)"
如何将表模式替换为父对象的适当键?
这是jq玩的例子
预期结果是:
[ "schema1.table2", "schema2.table2" ]
我选择了这样的解决方案
path(.[]|.[]|select(.status==1))|join(".")
下面使用 to_entries
(两次(根据请求生成数组:
[to_entries[]
| .key as $k
| .value | to_entries | map(select(.value.status == 1))[]
| [$k, .key]
| join(".") ]
如果输入文档太大以至于无法舒适地放入内存中,那么使用 jq 的流式解析器的解决方案将是合适的。
为此,请考虑 program.jq,如下所示:
select(length==2 and .[-1] == 1 and .[0][-1] == "status")
| .[0][:-1]
| join(".")
(这里[:-1]
是一种紧凑的[0:-1]
写法,它实际上接受数组中除最后一项之外的所有项目。
调用:jq --stream -f program.jq input.json
将生成流:
"schema1.table2"
"schema2.table2"
如果需要值数组,可以将此流传送到jq -s .
另请注意,如上所述的 program.jq 实际上解决了嵌套可以任意深度的一般问题。
jq
解决方案:
jq -r '. as $o | paths
| select(length == 3)
| select($o[.[0]][.[1]][.[2]] == 1)
| .[0] +"."+ .[1]' file.json
输出:
schema1.table2
schema2.table2
在这种情况下,您可以使用paths(scalars)
(以前称为 leaf_paths
(来获取所有标量值的路径。使用这些路径,您可以使用 getpath/1
来获取值并输出所需的字符串。
paths(scalars) as $p
| select($p[-1] == "status" and getpath($p) == 1)
| "([$p[1,0]] | join(".")) (getpath($p))"
如果你想花哨,你也可以使用流一次性获取路径和值。
tostream as [$p,$v]
| select($p[-1] == "status" and $v == 1)
| "([$p[1,0]] | join(".")) ($v)"
但是考虑到您的评论,如果您只需要路径,则可以简单地归结为:
[tostream as [$p,$v]
| select($p[-1] == "status" and $v == 1)
| $p[:2] | join(".")
]