我想将两个或多个文件聚合到一个json中,并在同一键下聚合数组。
file1.json
{
"shapes": [
{
"id": "1",
"name": "circle"
},
{
"id": "2",
"name": "square"
}
]
}
file2.json
{
"shapes": [
{
"id": "3",
"name": "triangle"
}
]
}
预期结果:
{
"shapes": [
{
"id": "1",
"name": "circle"
},
{
"id": "2",
"name": "square"
},
{
"id": "3",
"name": "triangle"
}
]
}
我可以使用以下jq命令执行此操作:
jq -s '{shapes: map(.shapes)|add }' file*.json
但这需要我知道 shapes 属性并对其进行硬编码。有没有简单的方法,我无需显式使用键名就能得到相同的结果?
答案 0 :(得分:1)
这是一个解决方案,它也解决了一个更一般的问题:首先,它可以任意处理许多输入文件;第二,假设每个顶级键都是数组值,它就为每个键按键形成“求和”。
通用函数:
# the values at each key are assumed to be arrays
def aggregate(stream):
reduce stream as $o ({};
reduce ($o|keys_unsorted[]) as $k (.;
.[$k] += $o[$k] ));
为避免“拖拉”,我们将使用inputs
:
aggregate(inputs)
因此,调用必须使用-n命令行选项:
jq -n -f program.jq *.json
答案 1 :(得分:1)
这是一个适用于每个顶级对象只有一个键的解决方案,它既高效又概念简单。假定使用-n选项调用了jq。
reduce inputs as $in (null;
($in|keys_unsorted[0]) as $k | { ($k): (.[$k] + $in[$k]) })
或更紧凑:
reduce inputs as $in (null; ($in|keys_unsorted[0]) as $k | .[$k] += $in[$k] )
答案 2 :(得分:0)
尝试以下代码。这可以处理任意数量的文件。假定所有输入都是json对象,其中所有值都作为数组。所有此类数组在按键分组后进行汇总。它输出一个对象,该对象的键与对应的聚合数组关联。
jq -s 'map(to_entries)|add|group_by(.key)|
map( { "key": (.[0].key), "value": (map(.value)|add)})|
from_entries' file1.json file2.json
对于您的示例输入,它给出:
{
"shapes": [
{
"id": "1",
"name": "circle"
},
{
"id": "2",
"name": "square"
},
{
"id": "3",
"name": "triangle"
}
]
}