jq:递归合并对象并连接数组 [英] jq: recursively merge objects and concatenate arrays
问题描述
我有两个 json 文件,orig.json 和 patch.json,它们具有相似的格式.
I have two json files, orig.json and patch.json, which have similar formats.
orig.json:
{
"a": {
"a1": "original a1",
"a2": "original a2",
"list": ["baz", "bar"]
},
"b": "original value B"
}
patch.json:
patch.json:
{
"a": {
"a1": "patch a1",
"list": ["foo"]
},
"c": "original c"
}
目前我正在使用 jq
递归合并它们.但是,jq 对列表的默认行为只是重新分配.使用 $ jq -s '.[0] 从 jq 输出的示例* .[1]' orig.json patch.json
:
Currently I am using jq
to merge them recursively. However, jq's default behavior for lists is just reassignment. Example output from jq using $ jq -s '.[0] * .[1]' orig.json patch.json
:
{
"a": {
"a1": "patch a1",
"a2": "original a2",
"list": [
"foo"
]
},
"b": "original value B",
"c": "original c"
}
注意 a.list
现在等于 patch.json 的 a.list
.我希望新的 a.list
成为 orig.json 的列表和 patch.json 的列表合并.换句话说,我希望 a.list
等于 ["baz", "bar", "foo"]
.
Note that a.list
is now equal to patch.json's a.list
. I want The new a.list
to be orig.json's list and patch.json's lists merged. In other words, I want a.list
to equal ["baz", "bar", "foo"]
.
有没有一种方法可以用 jq 轻松地做到这一点,也许是通过覆盖数组的默认合并策略?
Is there a way I can easily do this with jq, perhaps by overriding the default merge strategy for arrays?
推荐答案
这里是一个通用函数,它通过在同一位置连接数组来递归地组合两个复合 JSON 实体:
Here is a generic function that recursively combines two composite JSON entities by concatenating arrays at the same position:
# Recursively meld a and b,
# concatenating arrays and
# favoring b when there is a conflict
def meld(a; b):
a as $a | b as $b
| if ($a|type) == "object" and ($b|type) == "object"
then reduce ([$a,$b]|add|keys_unsorted[]) as $k ({};
.[$k] = meld( $a[$k]; $b[$k]) )
elif ($a|type) == "array" and ($b|type) == "array"
then $a+$b
elif $b == null then $a
else $b
end;
融合输出($orig; $patch)
将 $orig 设置为 orig.json 的内容和$patch 设置为 patch.json 的内容:
Output of meld($orig; $patch)
With $orig set to the contents of orig.json and $patch set to the contents of patch.json:
{
"a": {
"a1": "patch a1",
"a2": "original a2",
"list": [
"baz",
"bar",
"foo"
]
},
"b": "original value B",
"c": "original c"
}
这篇关于jq:递归合并对象并连接数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!