我想要合并两个 JSON 文件,其中基础文件 (A) 中的对象通过文件 (B) 中的匹配对象进行扩充,但不会被覆盖,因为 A 和 B 的同一键具有不同的值。
例如,我有一个 JSON 文件 (A),其内容如下
[
{
"name": "alpha",
"value": "apple"
},
{
"name": "beta",
"value": "banana"
},
{
"name": "gamma",
"value": "guava"
}
]
和第二个 JSON 文件 (B),具有相同的基本结构,但可选地具有附加键(本例中为元数据
,但它可以是任何内容):
[
{
"name": "alpha",
"value": "apple",
"metadata": {
"types": [
"granny"
]
}
},
{
"name": "beta",
"value": "blueberry"
},
{
"name": "omega",
"value": "orange"
}
]
我想将两个列表合并在一起,B 中对象的键/值被添加到 A 中的同一个对象(由 name
匹配)中。我的 JQ 实现这一点的方法如下:
jq -s '[ .[0][] as $a | .[1][] as $b | select ($a.name == $b.name) | $a * $b ]' b.json a.json
这可以将元数据
添加到A中并保留A的其他键值。但是,结果中缺少 gamma
。从上面的示例中,我想要一个结果:
- alpha 应该有元数据
- beta 应该是香蕉,而不是蓝莓。
- gamma 应该在最终列表中
- omega 不应出现在最终列表中
- 应保持列表中对象的顺序。
我想要这个:
[
{
"name": "alpha",
"value": "apple"
"metadata": {
"types": [
"granny"
]
}
},
{
"name": "beta",
"value": "banana"
},
{
"name": "gamma",
"value": "guava"
}
]
如何调整此查询以包含来自 A 的顶级对象,但不包含来自 B 的顶级对象?
最佳答案
如果保证名称在一个文件中是唯一的,您可以暂时将文件 A 转换为 INDEX
,因此检查 .name
的包含性就变成了以下问题使用 has
检查 key 。然后,在 input[]
上使用 reduce
迭代文件 B 的项目,如果名称作为键存在,则通过将其旧值添加到当前项目(订单事宜)。最后,使用 [.[]]
将所有字段值收集到数组中,将对象结构恢复为数组。
jq 'reduce input[] as $i (INDEX(.name);
if has($i.name) then .[$i.name] |= $i + . end
) | [.[]]' fileA.json fileB.json
[
{
"name": "alpha",
"value": "apple",
"metadata": {
"types": [
"granny"
]
}
},
{
"name": "beta",
"value": "banana"
},
{
"name": "gamma",
"value": "guava"
}
]
关于json - 使用 JQ 合并 JSON 列表中的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77299198/