JQ工具库问题:如何用另一JSON对象递归覆盖现有键值且不新增属性
用JQ实现顶层保留目标结构、嵌套层级合并替换
从你的示例来看,需求是:
- 顶层仅保留config_new.json的键,用config.json中对应键的值替换
- 嵌套对象层级:合并config.json的键到config_new.json的嵌套对象中(允许嵌套层级添加config里的额外键)
原命令用*会把config的顶层额外键也带入,不符合要求,下面是精准实现的命令:
解决命令
jq -n ' (inputs | .) as $config_new | input as $config | $config_new | with_entries( .value = ( if .value | type == "object" and $config[.key] | type == "object" then .value + $config[.key] else $config[.key] // .value end ) ) ' config_new.json config.json
命令说明
- 读取输入:先加载config_new作为目标结构,再加载config作为替换源
- 处理顶层键:用
with_entries遍历config_new的所有顶层键,确保只保留这些键 - 值替换逻辑:
- 如果当前键对应的值是对象,且config中该键的值也是对象,就合并两个对象(config的嵌套键会被加入)
- 否则,优先用config中的值替换,没有的话保留config_new原有的值
验证结果
用你提供的文件执行命令后,输出和你期望的完全一致:
{ "name": "testName", "age": "tooYoung", "properties": { "title": "Mr", "fruits": ["banana"], "height": "tooTall" } }
如果你需要所有层级都严格只保留config_new的键(包括嵌套层级不添加额外键),可以用下面的递归命令:
jq -n ' def deep_merge_strict($source): . as $target | reduce keys[] as $key ( {}; if $target[$key] | type == "object" and $source[$key] | type == "object" then .[$key] = ($target[$key] | deep_merge_strict($source[$key])) elif $source | has($key) then .[$key] = $source[$key] else .[$key] = $target[$key] end ); (inputs | .) as $config_new | input as $config | $config_new | deep_merge_strict($config) ' config_new.json config.json
这个命令执行后,嵌套层级的height不会被保留,因为config_new的properties里没有这个键。
内容的提问来源于stack exchange,提问作者Dog
相关产品推荐
相关产品推荐

