如何用通配符与键名过滤JSON,处理对象与数组混合结构
解决混合JSON结构的过滤需求
问题说明
原始JSON数据包含对象与数组混合的结构,需要过滤每个元素,仅保留enabled键,以及存在的name键:
原始JSON:
{ "abc": { "enabled": true }, "def": { "enabled": false }, "ghi": [ { "enabled": false, "name": "HELLO", "useless": "DO NOT WANT THIS" } ], "jkl": [ { "enabled": true, "name": "HI" } ], "mko": { "enabled": false, "something unwanted": 123 }, "pqr": { "enabled": true } }
期望过滤后的结果:
{ "abc": { "enabled": true }, "def": { "enabled": false }, "ghi": [ { "enabled": false, "name": "HELLO" } ], "jkl": [ { "enabled": true, "name": "HI" } ], "mko": { "enabled": false }, "pqr": { "enabled": true } }
之前尝试的jq -r '[*].enabled' file命令报错,原因是[*]不是jq的合法语法,且该命令既没区分数组与对象的处理逻辑,也没考虑保留name键的需求。
正确的jq命令
使用以下命令即可实现需求:
jq 'with_entries(.value |= (if type == "array" then map({enabled} + (select(.name) | {name})) else {enabled} + (select(.name) | {name}) end))' input.json
命令解释
with_entries:遍历顶层的每一组键值对,专注处理每个值的内容.value |= ...:对每个值执行后续的修改逻辑if type == "array" then ... else ... end:判断当前值是数组还是对象,分别处理- 数组场景:
map({enabled} + (select(.name) | {name}))遍历数组内的每个元素,保留enabled键;如果元素存在name键,就追加该键值对 - 对象场景:
{enabled} + (select(.name) | {name})保留对象的enabled键;如果对象存在name键,就追加该键值对
- 数组场景:
执行该命令后,会输出符合预期的过滤结果,既不会保留多余的键(比如useless、something unwanted),也不会在没有name键的元素中添加null值的name字段。
内容的提问来源于stack exchange,提问作者monk
相关产品推荐
相关产品推荐

