如何在jq的select()调用中保留不含指定字段的对象
使用jq提取含可选数组字段的JSON数据
需求
从JSON数组的每个对象中提取field1、field2,以及Tags数组中Key为Name的Value值。若对象的Tags中没有Name标签,仍需保留该对象的其他字段输出,不能跳过记录,也不能因Tags中的其他元素生成重复行。
示例数据
[ {"field1":"1", "field2":"x", "Tags":[{"Key": "Name", "Value": "Name1"}, {"Key": "tag1", "Value": "tag1valuea"}]}, {"field1":"2", "field2":"y", "Tags":[{"Key": "Name", "Value": "Name2"}]}, {"field1":"3", "field2":"z", "Tags":[{"Key": "tag2", "Value": "tag2valueb"}]} ]
期望输出
1 x Name1 2 y Name2 3 z
尝试过的命令及问题
第一个命令:
jq -r '.[] | .field1 + " " + .field2 + " " + (.Tags[] | select(.Key == "Name") .Value)'问题:会跳过没有
Name标签的第3条记录,仅输出前两行。第二个命令:
jq -r '.[] | .field1 + " " + .field2 + " " + (.Tags[] | if(.Key == "Name") then .Value else null end)'问题:
Tags数组中的非Name元素会生成重复行,比如第一个对象会输出两行内容。
解决方案
方法1:将Tags数组转为键值对对象(推荐)
利用from_entries把Tags数组转换为以Key为键、Value为值的对象,直接提取Name属性,没有该属性则用空字符串替代:
jq -r '.[] | .field1 + " " + .field2 + " " + (.Tags | from_entries | .Name // "")'
方法2:查找数组中第一个匹配的元素
用first函数定位Tags数组中第一个Key为Name的元素的Value,找不到则用空字符串替代:
jq -r '.[] | .field1 + " " + .field2 + " " + (.Tags | first(.[] | select(.Key == "Name").Value) // "")'
两种方法的输出均符合期望,既不会跳过无Name标签的记录,也不会因Tags中的其他元素生成重复行。
内容的提问来源于stack exchange,提问作者kcantrel
相关产品推荐
相关产品推荐

