如何用jq提取嵌套JSON指定键值对为顶级字段,缺失值设为null?
问题:解析嵌套JSON为顶级字段并处理缺失值
需要查询JSON数据,将嵌套的键值对解析为输出中的顶级字段;当部分输入行不存在对应键值对时,用null作为默认值。处理嵌套数组的select过滤逻辑时遇到问题,寻求解决方法。
输入示例
{ "id": "123", "details": [ { "headerText": "ignore_me", "rows": [ { "key": "label1", "val": "sdhf" }, { "key": "label2", "val": "fdgg" } ] }, { "headerText": "only_look_at_kvs_here", "rows": [ { "key": "label3", "val": "abc" }, { "key": "label4", "val": "def" }, { "key": "label5", "val": "qwe" } ] } ] } { "id": "345", "details": [ { "headerText": "ignore_me", "rows": [ { "key": "label1", "val": "abc" }, { "key": "label2", "val": "def" } ] }, { "headerText": "only_look_at_kvs_here", "rows": [ { "key": "label1", "val": "foo" }, { "key": "label2", "val": "bar" } ] } ] } { "id": "789", "details": [ { "headerText": "ignore_me", "rows": [ { "key": "label1", "val": "abc" }, { "key": "label2", "val": "def" } ] } ] }
预期输出
{ "id": "123", "label1": null, "label2": null, "label3": "abc", "label4": "def" } { "id": "345", "label1": "foo", "label2": "bar", "label3": null, "label4": null } { "id": "789", "label1": null, "label2": null, "label3": null, "label4": null }
尝试的命令
jq '{id, "label1": (.details[] | select(.headerText=="only_look_at_kvs_here") | .rows[] | select(.key=="label1") | .val) }'
解决方法
原命令的问题在于:当没有匹配的details项或rows项时,select会直接过滤掉该结果,导致对应字段缺失而非返回null。可以通过以下jq命令实现需求:
jq ' .target_rows = (.details[] | select(.headerText == "only_look_at_kvs_here") | .rows) // [] | .target_rows |= from_entries | { id, label1: .target_rows.label1 // null, label2: .target_rows.label2 // null, label3: .target_rows.label3 // null, label4: .target_rows.label4 // null } | del(.target_rows) '
命令解释
- 定位目标行:通过
.details[] | select(...)找到headerText为only_look_at_kvs_here的details项,提取其rows数组;如果没有匹配项,用// []返回空数组,避免后续处理出错。 - 转换为键值对对象:用
from_entries将rows数组(每个元素是{key, val}结构)转换为普通键值对对象,方便直接取值。 - 构造结果对象:指定需要的
label1到label4字段,用// null确保当目标对象中没有对应键时,自动填充null。 - 清理临时字段:删除临时创建的
target_rows字段,得到最终的预期输出。
内容的提问来源于stack exchange,提问作者Daniel Resnick
相关产品推荐
相关产品推荐

