如何用jq合并多个含数组值的对象并拼接同键数组?
使用jq合并JSON对象并拼接同键数组(兼容null转空数组)
需求说明
需要合并两个JSON对象,满足:
- 同键的数组值拼接而非覆盖
- 非数组键按常规合并(右侧对象的键覆盖左侧,无对应键的保留原有值)
- 将值为
null的数组键视为空数组处理
比如输入:
{"messages":["one"], "keyA": "valueA"} {"messages":["two"], "keyB": "valueB"}
期望输出:
{"messages":["one","two"], "keyA": "valueA", "keyB": "valueB"}
又比如输入含null的情况:
{"messages":null, "keyA": "valueA"} {"messages":["two"], "keyB": "valueB"}
期望输出:
{"messages":["two"], "keyA": "valueA", "keyB": "valueB"}
解决方案
使用jq的reduce遍历处理每个键,针对数组和null做特殊处理,命令如下:
# 示例1:合并两个常规JSON对象 echo '{"messages":["one"], "keyA": "valueA"}{"messages":["two"], "keyB": "valueB"}' | jq -s ' reduce .[] as $obj ({}; reduce ($obj | keys)[] as $k (.; .[$k] = ( let curr = .[$k] // [], next = if $obj[$k] == null then [] else $obj[$k] end; if (curr | type) == "array" and (next | type) == "array" then curr + next else next end ) ) ) '
# 示例2:处理含null的JSON对象 echo '{"messages":null, "keyA": "valueA"}{"messages":["two"], "keyB": "valueB"}' | jq -s ' reduce .[] as $obj ({}; reduce ($obj | keys)[] as $k (.; .[$k] = ( let curr = .[$k] // [], next = if $obj[$k] == null then [] else $obj[$k] end; if (curr | type) == "array" and (next | type) == "array" then curr + next else next end ) ) ) '
代码解释
-s选项:将输入的多个JSON对象转为一个数组,方便逐个处理- 外层
reduce:从空对象开始,逐个合并输入的每个JSON对象 - 内层
reduce:遍历当前对象的所有键,对每个键做如下处理:curr = .[$k] // []:如果当前结果中无此键,默认用空数组占位next = if $obj[$k] == null then [] else $obj[$k] end:将当前对象中该键的null值转为空数组- 若
curr和next都是数组,则拼接两者;否则直接用next覆盖(或添加)当前键值
内容的提问来源于stack exchange,提问作者levigroker
相关产品推荐
相关产品推荐

