When using this algorithm:
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({}; .)' test1.json test2.json > merged-1.json
nested arrays are not concatenated/merged, but copied sequentially. I assume this is because when the method stack created by the recursive algorithm unwinds, values are written in the order node >> root, and deeper nested child values are thus always overwritten by their higher parents.
Input files:
test1.json
{
"item1" : "test1",
"item2" : "test2",
"nestedItemsArray1" : [{
"nestedItem1Item1" : "nestItem1Item1",
"nestedItem1Array1" : ["nestedItem1Array1Item1", "nestedItem1Array1Item2"]
},
{
"nestedItem1Item1" : "nestItem1Item2",
"nestedItem1Array1" : ["nestedItem1Array1Item3", "nestedItem1Array1Item4"]
}]
}
test2.json
{
"item1" : "test3",
"item2" : "test4",
"array1" : [ "array1item3", "array1item4" ],
"nestedItemsArray1" : [{
"nestedItem1Item1" : "nestItem1Item1",
"nestedItem1Array1" : ["nestedItem1Array1Item5", "nestedItem1Array1Item6"]
},
{
"nestedItem1Item1" : "nestItem1Item2",
"nestedItem1Array1" : ["nestedItem1Array1Item7", "nestedItem1Array1Item8"]
}]
}
Actual result:
{
"item1": "test3",
"item2": "test4",
"nestedItemsArray1": [
{
"nestedItem1Item1": "nestItem1Item1",
"nestedItem1Array1": [
"nestedItem1Array1Item1",
"nestedItem1Array1Item2"
]
},
{
"nestedItem1Item1": "nestItem1Item2",
"nestedItem1Array1": [
"nestedItem1Array1Item3",
"nestedItem1Array1Item4"
]
},
{
"nestedItem1Item1": "nestItem1Item1",
"nestedItem1Array1": [
"nestedItem1Array1Item5",
"nestedItem1Array1Item6"
]
},
{
"nestedItem1Item1": "nestItem1Item2",
"nestedItem1Array1": [
"nestedItem1Array1Item7",
"nestedItem1Array1Item8"
]
}
],
"array1": [
"array1item3",
"array1item4"
]
}
Expected result:
{
"item1": "test3",
"item2": "test4",
"nestedItemsArray1": [
{
"nestedItem1Item1": "nestItem1Item1",
"nestedItem1Array1": [
"nestedItem1Array1Item1",
"nestedItem1Array1Item2",
"nestedItem1Array1Item5",
"nestedItem1Array1Item6"
]
},
{
"nestedItem1Item1": "nestItem1Item2",
"nestedItem1Array1": [
"nestedItem1Array1Item3",
"nestedItem1Array1Item4",
"nestedItem1Array1Item7",
"nestedItem1Array1Item8"
]
}
],
"array1": [
"array1item3",
"array1item4"
]
}
Of course this is just one array deep, but I would like this to work on any number of nested levels, regardless of values being nested inside arrays or objects.