You have pretty complex structure to merge, no standard functions will help here, and custom written ones will highly depend on what do you want
If you don't mind order of array elements, and keys doesn't repeat, then this will work:
local
// Extract "key" out of {key: ...}
unionName(u) = assert std.length(u) == 1; std.objectFields(u)[0],
// Convert [{a: ...}, {b: ...}] to {a: ..., b: ...}
mergeArrsToObject(arr) = {
[unionName(el)]: el[unionName(el)] for el in arr
},
// Inverse of mergeArrsToObject
splitArrsFromObject(obj) = [
{[key]: obj[key]} for key in std.objectFields(obj)
],
// Custom merge logic implemented for object:
// here I add values from both, and then sort & deduplicate
mergeObjects(a, b) = {
[key]: std.set(std.get(a, key, []) + std.get(b, key, []))
for key in std.set(std.objectFields(a) + std.objectFields(b))
},
merge(a, b) = splitArrsFromObject(mergeObjects(
mergeArrsToObject(a),
mergeArrsToObject(b),
))
;
merge([
{"key1":["val1"]},
{"key2":["val2", "val3"]}
], [
{"key2":["val2", "val4"]},
{"key3":["val5"]}
]) == [
{"key1":["val1"]},
{"key2":["val2", "val3", "val4"]},
{"key3":["val5"]}
]