我有以下两个json作为输入:
{
"one": {
"vars": [
{
"name": "a",
"value": "a"
},
{
"name": "b",
"value": "b"
}
]
},
"two": {
"vars": [
{
"name": "c",
"value": "c"
},
{
"name": "d",
"value": "d"
}
]
},
"extras": "whatever"
}
{
"one": {
"vars": [
{
"name": "e",
"value": "e"
},
{
"name": "f",
"value": "f"
}
]
},
"two": {
"vars": [
{
"name": "g",
"value": "g"
},
{
"name": "h",
"value": "h"
}
]
}
}
我想将它们合并,以获得以下结果,其中每个部分的每个vars
数组都合并在一起:
{
"one": {
"vars": [
{
"name": "a",
"value": "a"
},
{
"name": "b",
"value": "b"
},
{
"name": "e",
"value": "e"
},
{
"name": "f",
"value": "f"
}
]
},
"two": {
"vars": [
{
"name": "c",
"value": "c"
},
{
"name": "d",
"value": "d"
},
{
"name": "g",
"value": "g"
},
{
"name": "h",
"value": "h"
}
]
},
"extras": "whatever"
}
理想但非必需:
one
和two
)将是任意的,并且可能存在未定义的数量。vars
数组将不包含重复项(基于name
),并且将使用优先级优先来覆盖第一个数组中的值。我使用以下命令设法合并了两个对象和只有1个数组,但是密钥是硬编码的,因此我有点卡住了:
jq -s '.[0].one.vars=([.[].one.vars]|flatten)|.[0]' file1.json file2.json
答案 0 :(得分:2)
jq -n 'input as $b | input
| .one.vars |= . + $b.one.vars
| .two.vars |= . + $b.two.vars' file2.json file1.json
file1.json
必须紧跟file2.json
之后才能保留extras
。
答案 1 :(得分:2)
首先,这是一个不使用顶级键名的解决方案,但它并不试图避免重复:
$A
| reduce keys_unsorted[] as $k (.;
if .[$k] | (type == "object") and has("vars")
then (.[$k]|.vars) += ($B[$k]|.vars) else . end )
这里$ A和$ B当然是指两个对象。您可以通过几种方式设置$ A和$ B。
如果您想对顶级键进行重新排序,只需使用指定顺序的过滤器即可扩展上述内容,例如:{extras, two, one}
。
为避免重复,我建议编写一个辅助函数来做到这一点,如以下部分所示。
def extend(stream):
reduce stream as $s (.;
(map(.name) | index($s|.name)) as $i
| if $i then .[$i] += $s
else . + [$s]
end) ;
$A
| reduce keys_unsorted[] as $k (.;
if .[$k] | (type == "object") and has("vars")
then (.[$k].vars) = ( .[$k].vars | extend(($B[$k].vars[])))
else . end
)