如何用JQ合并JSON列表对象:保留A文件内容并补充匹配B项
JQ合并JSON文件:保留基准内容并补充新键值
需求说明
- 以JSON文件A为基准,合并文件B的内容
- 按
name字段匹配对应对象 - 核心规则:
- 补充B中对象的新键值到A的对应对象,但不覆盖A中已存在的同键不同值
- 保留A中所有对象,排除B中A没有匹配的对象
- 维持A的原始对象顺序
原命令问题
原命令jq -s '[ .[0][] as $a | .[1][] as $b | select ($a.name == $b.name) | $a * $b ]' b.json a.json存在两个问题:
- 仅保留A和B都有的对象,丢失A中无匹配的对象(比如示例中的gamma)
$a * $b会用B的键值覆盖A的同键内容,不符合“不覆盖”要求
修正后的JQ命令
jq -s ' (.[1] | INDEX(.name)) as $b_map | .[0][] | . + ($b_map[.name] | del(.name) // {}) ' a.json b.json
命令解释
- 构建B的映射表:
(.[1] | INDEX(.name)) as $b_map- 将文件B的数组转换为以
name为键的对象,通过name可以快速查找B中对应的对象,避免嵌套遍历的低效和遗漏问题
- 将文件B的数组转换为以
- 遍历A并合并:
.[] | . + ($b_map[.name] | del(.name) // {})- 遍历文件A的每个对象,用
+操作符合并B中匹配的对象内容 del(.name):移除B对象中的name字段,避免重复(若允许重复可省略)// {}:当B中无匹配对象时,用空对象代替null,确保合并操作不报错且保留原对象
- 遍历文件A的每个对象,用
- 文件顺序:命令中先传入
a.json再传入b.json,对应-s模式下数组的.0(基准文件)和.1(补充文件)
示例验证
假设a.json内容:
[ {"name": "alpha", "value": "apple"}, {"name": "beta", "value": "banana"}, {"name": "gamma", "value": "cherry"} ]
b.json内容:
[ {"name": "alpha", "value": "apricot", "metadata": "from B"}, {"name": "beta", "value": "blueberry"}, {"name": "omega", "value": "orange"} ]
执行修正后的命令,输出结果:
{ "name": "alpha", "value": "apple", "metadata": "from B" } { "name": "beta", "value": "banana" } { "name": "gamma", "value": "cherry" }
完全符合需求:alpha保留A的value并新增metadata;beta保留A的value;gamma完整保留;omega被排除;顺序与A完全一致。
内容的提问来源于stack exchange,提问作者Jumwah
相关产品推荐
相关产品推荐

