如何使用jq reduce将数组转为分组对象及报错排查
使用jq的reduce方法分组JSON数组报错问题
输入JSON数组
[ {"cat": "low", "value": "1"}, {"cat": "med", "value": "2"}, {"cat": "med", "value": "3"} ]
期望输出
{ "low": [ { "cat": "low", "value": "1" } ], "med": [ { "cat": "med", "value": "2" }, { "cat": "med", "value": "3" } ] }
编写的jq代码
reduce .[] as $curr ({}; $curr.cat as $category | # 存储当前分类,比如"low" .[$category] as $currArray | # 获取当前分类对应的数组 $currArray + [($curr)] as $newCategoryArray | # 将当前对象加入数组 . + {($category): ($newCategoryArray)} # 更新累加器 )
报错信息
jq: error (at <stdin>:5): array ([{"cat":"me...) and object ({"low":[{"c...) cannot be added exit status 5
注:输入数组中分类唯一时代码可正常运行,仅分类重复时触发报错。
问题原因
报错的核心是第一次处理重复分类时,$currArray的值为null。当首次处理med分类时,累加器里还没有med这个键,.[$category]会返回null;而jq中null + [数组]会把null当作空对象处理,导致$newCategoryArray变成对象与数组非法相加的结果,后续执行. + {($category): ...}时就会触发类型不匹配的报错。
修正后的代码
只需在获取$currArray时,用// []将null替换为空数组即可:
reduce .[] as $curr ({}; $curr.cat as $category | (.[$category] // []) as $currArray | # 若分类不存在,用空数组替代null $currArray + [$curr] as $newCategoryArray | . + {($category): $newCategoryArray} )
或者用更简洁的写法,直接利用+=操作符自动处理空值:
reduce .[] as $curr ({}; .[$curr.cat] += [$curr])
代码解释
// []:jq的空值合并操作,当目标键不存在时返回空数组,保证后续数组拼接操作合法。- 简洁写法中,
.[$curr.cat] += [$curr]会自动处理键不存在的情况:若分类未在累加器中,jq会先创建该键并赋值为空数组,再执行追加操作,逻辑与前者一致但更精简。
内容的提问来源于stack exchange,提问作者tg0h
相关产品推荐
相关产品推荐

