You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键调整说明

  1. 对象合并逻辑优化:将deepmerge({}; [existing, $val])改为deepmerge(existing // {}; [$val]),直接基于已有对象递归合并,避免创建新空对象覆盖原有内容。
  2. 对象数组分组合并:判断数组元素为对象时,将两个数组合并后按nestedItem1Item1分组,每组内的对象递归调用deepmerge合并内部结构,实现同标识对象的嵌套数组合并。
  3. 兼容普通数组:非对象元素的数组仍保持拼接去重的逻辑。

验证结果

执行修改后的命令,得到的结果与期望一致:

{
  "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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:13:11