JQ递归deepmerge算法无法深度合并嵌套数组问题求助
修复jq深度合并中嵌套对象数组的合并问题
原递归合并算法遇到嵌套的对象数组时,只是简单将两个数组的元素拼接在一起,没有根据对象的标识键合并对应项的内部嵌套数组。要实现按标识合并对象数组并递归处理内部嵌套结构,需要调整数组的合并逻辑:
原问题代码
jq -s 'def deepmerge(a;b): reduce b[] as $item (a; reduce ($item | keys_unsorted[]) as $key (.; $item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "object") then deepmerge({}; [if .[$key] == null then {} else .[$key] end, $val]) elif ($type == "array") then (.[$key] + $val | unique) else $val end) ); deepmerge({}; .)' test1.json test2.json > merged-1.json
问题分析
原代码对数组的处理逻辑是直接拼接后去重,但对于包含对象的数组,这种方式会把两个数组中的对象都保留,而不会根据对象的唯一标识(比如示例中的nestedItem1Item1)匹配并合并对象内部的嵌套数组。
解决方案
修改deepmerge函数,针对对象数组增加分组合并逻辑:当合并的数组元素是对象时,先将两个数组合并,然后按对象的标识键分组,每组内的对象递归合并;对于普通非对象数组,保持原有的拼接去重逻辑。
修改后的命令:
jq -s 'def deepmerge(a;b): reduce b[] as $item (a; reduce ($item | keys_unsorted[]) as $key (.; $item[$key] as $val | ($val | type) as $type | .[$key] = if $type == "object" then deepmerge(.[$key] // {}; [$val]) elif $type == "array" then if ($val[0] | type) == "object" then # 按nestedItem1Item1分组合并对象数组,可根据需求调整标识键 (.[$key] // []) + $val | group_by(.nestedItem1Item1) | map(reduce .[] as $obj ({}; deepmerge(.; [$obj]))) else (.[$key] // []) + $val | unique end else $val end ) ); deepmerge({}; .)' test1.json test2.json > merged-1.json
关键调整说明
- 对象合并逻辑优化:将
deepmerge({}; [existing, $val])改为deepmerge(existing // {}; [$val]),直接基于已有对象递归合并,避免创建新空对象覆盖原有内容。 - 对象数组分组合并:判断数组元素为对象时,将两个数组合并后按
nestedItem1Item1分组,每组内的对象递归调用deepmerge合并内部结构,实现同标识对象的嵌套数组合并。 - 兼容普通数组:非对象元素的数组仍保持拼接去重的逻辑。
验证结果
执行修改后的命令,得到的结果与期望一致:
{ "item1": "test3", "item2": "test4", "nestedItemsArray1": [ { "nestedItem1Item1": "nestItem1Item1", "nestedItem1Array1": [ "nestedItem1Array1Item1", "nestedItem1Array1Item2", "nestedItem1Array1Item5", "nestedItem1Array1Item6" ] }, { "nestedItem1Item1": "nestItem1Item2", "nestedItem1Array1": [ "nestedItem1Array1Item3", "nestedItem1Array1Item4", "nestedItem1Array1Item7", "nestedItem1Array1Item8" ] } ], "array1": [ "array1item3", "array1item4" ] }
如果需要支持任意嵌套层级的通用合并,可将分组的标识键改为动态判断(比如自动识别对象的唯一键,或允许传入参数),但基于当前示例的需求,上述代码已能实现嵌套数组的正确合并。
内容的提问来源于stack exchange,提问作者staxas
相关产品推荐
相关产品推荐

