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

如何使用jq递归合并Bash JSON字符串与JSON文件?

解决JSON递归合并问题

问题分析

你之前的命令存在两个核心问题:

  1. Shell分词错误:$(echo $default)会把JSON中的空格、换行作为分隔符,将完整JSON拆成多个片段传给jq,jq会把这些片段当成文件名,导致读取失败。
  2. 浅合并不满足需求:jq的*操作符是浅合并,会直接用override的顶层键值对替换default的对应项,不会递归合并嵌套对象(比如horses下的子键)。

正确解决方案

方法一:使用jq内置deepmerge函数(jq 1.6及以上版本推荐)

jq 1.6及以上内置了deepmerge函数,可直接实现递归合并,同时通过--argjson正确传递Bash变量:

jq --argjson default "$default" '$default | deepmerge(input)' override.json

或者通过标准输入传递default变量:

echo "$default" | jq -n 'input | deepmerge(input)' - override.json

其中-代表从标准输入读取第一个JSON(即default的内容),override.json是第二个输入源。

方法二:自定义递归合并函数(兼容旧版本jq)

如果你的jq版本低于1.6,可以自定义递归合并函数实现需求:

jq --argjson default "$default" '
def deepmerge(a; b):
  reduce b[] as $item (a;
    reduce ($item | keys_unsorted[]) as $key (.;
      if ($item[$key] | type) == "object" and (.[$key] | type) == "object"
      then .[$key] = deepmerge(.[$key]; $item[$key])
      else .[$key] = $item[$key]
      end
    )
  );
deepmerge($default; input)' override.json

结果验证

执行上述命令后,会得到你期望的递归合并结果:

{
    "horses": {
        "count": 1,
        "fizz": "buzz",
        "foo": "bar"
    },
    "admin": {
        "enabled": true
    }
}

内容的提问来源于stack exchange,提问作者blueski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:09:22