使用jq有条件地压平递归json



我能想到的输入文档的最简单版本是

{
"references": [
{
"version": 5,
"id": "id1",
"objType": "A"
},
{
"version": 4,
"id": "id2",
"objType": "B",
"referencing": []
},
{
"version": 4,
"id": "id3",
"objType": "B",
"referencing": [
{
"version": 2,
"id": "id4",
"objType": "A"
},
{
"version": 3,
"id": "id5",
"objType": "B",
"referencing": []
}
]
}
]
}

类型A的对象没有引用对象。

任何一种类型的对象都可以引用B类型的对象。

这个json需要两个输出:

输出#1是以id值为关键字、值为version的类型A对象的版本信息。CCD_ 3对象可以在CCD_。

{
"references": {
"id1": {"version": 5},
"id4": {"version": 2}
}
}

第二个输出类似:B类型对象的版本信息。可以是引用其他类型B对象的B类型对象链。

{
"references": {
"id2": {"version": 4},
"id3": {"version": 4},
"id5": {"version": 3}
}
} 

使用递归decsent运算符和from_entries。你不需要遵循";参考文献";(至少不会在你的问题中产生预期的输出(

{
dependencies: [.. | select(.objType=="A")? | { key: .id, value: {version} }] | from_entries
},
{
dependencies: [.. | select(.objType=="B")? | { key: .id, value: {version} }] | from_entries
}

输出:

{
"dependencies": {
"id1": {
"version": 5
},
"id4": {
"version": 2
}
}
}
{
"dependencies": {
"id2": {
"version": 4
},
"id3": {
"version": 4
},
"id5": {
"version": 3
}
}
}

也可以合并(添加(对象,而不是从它们的条目中构建它们,这使得代码至少更短:

{
dependencies: [.. | select(.objType=="A")? | { (.id): {version} }] | add
}

您可以使用recurse遍历文档,INDEX创建一个以ID为键的对象,map_values根据您的标准使用select格式化它们的值。

jq --arg type A '
.references |= (
INDEX(.[] | recurse(.referencing[]?); .id)
| map_values(select(.objType == $type) | {version})
)
'
{
"references": {
"id1": {
"version": 5
},
"id4": {
"version": 2
}
}
}

演示

这对两个问题都有效,将AB提供给--arg type

请注意,这是在向下递归时使用错误抑制运算符?。如果要将遍历显式限制为.objType == "B",只需在select表达式中加上前缀即可,即用recurse(select(.objType == "B") | .referencing[])替换recurse(.referencing[]?)。演示

最新更新