我有两个json文件,分别为orig.json和patch.json,它们的格式相似。
orig.json:
{
"a": {
"a1": "original a1",
"a2": "original a2",
"list": ["baz", "bar"]
},
"b": "original value B"
}
patch.json:
{
"a": {
"a1": "patch a1",
"list": ["foo"]
},
"c": "original c"
}
当前,我正在使用jq
递归合并它们。但是,jq的列表默认行为只是重新分配。使用$ jq -s '.[0] * .[1]' orig.json patch.json
从jq输出的示例:
{
"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"]
。
是否可以通过重写数组的默认合并策略轻松地使用jq做到这一点?
答案 0 :(得分:1)
这是一个通用函数,它通过在同一位置串联数组来递归地合并两个复合JSON实体:
# Recursively meld a and b,
# concatenating arrays and
# favoring b when there is a conflict
def meld(a; 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设置为orig.json的内容,然后 $ patch设置为patch.json的内容:
{
"a": {
"a1": "patch a1",
"a2": "original a2",
"list": [
"baz",
"bar",
"foo"
]
},
"b": "original value B",
"c": "original c"
}
答案 1 :(得分:0)
调用:
jq -f patch.jq --argfile patch patch.json orig.json
其中patch.jq包含:
(.a.list + $patch.a.list) as $a
| . + $patch
| .a.list = $a
产生:
{
"a": {
"a1": "patch a1",
"list": [
"baz",
"bar",
"foo"
]
},
"b": "original value B",
"c": "original c"
}
答案 2 :(得分:0)
$ jq -s 'def deepmerge(a;b):
reduce b[] as $item (a;
reduce ($item | keys_unsorted[]) as $key (.;
$item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "object") then
deepmerge({}; [if .[$key] == null then {} else .[$key] end, $val])
elif ($type == "array") then
(.[$key] + $val | unique)
else
$val
end)
);
deepmerge({}; .)' file1.json file2.json > merged.json