使用jq在嵌套数组中删除数据

5
这是我的数据结构:
[
    {
        "name": "name1",
        "organizations": [
            {
                "name": "name2",
                "spaces": [
                    {
                        "name": "name3",
                        "otherkey":"otherval"
                    },
                    {
                        "name": "name4",
                        "otherkey":"otherval"
                    }
                ]
            }
        ]
    },
    {
        "name": "name21",
        "organizations": [
            {
                "name": "name22",
                "spaces": [
                    {
                        "name": "name23",
                        "otherkey":"otherval"
                    },
                    {
                        "name": "name24",
                        "otherkey":"otherval"
                    }
                ]
            }
        ]
    }
]

我希望保留name=name1,删除嵌套的名为name4的数组对象,并保持其余对象不变。我尝试使用map(select),但这只会给我完整的对象。是否可以在特定子数组上使用del并保持其余部分不变?
结果应该如下所示。此外,我想避免枚举所有要在外部对象中保留的属性:
[
    {
        "name": "name1",
        "organizations": [
            {
                "name": "name2",
                "spaces": [
                    {
                        "name": "name3",
                        "otherkey":"otherval"
                    }
                ]
            }
        ]
    }
]

有什么想法吗?谢谢!

4个回答

5
一个非常有针对性的解决方案是:
path(.[0].organizations[0].spaces) as $target
| (getpath($target) | map(select(.name != "name4"))) as $new
| setpath($target; $new)

如果可以的话,您可以考虑以下几点:

walk(if type == "object" and .spaces|type == "array"
     then .spaces |= map(select(.name != "name4"))
     else . end)

或者:

del(.. | .spaces? // empty | .[] | select(.name == "name4") )

(如果您的jq没有walk/1,那么可以通过谷歌搜索轻松找到其jq定义。)

1
您可以使用下面的代码,它将仅删除"name": "name4"数组。
jq 'del(.[] | .organizations? | .[] | .spaces?|.[] | select(.name? == "name4"))' yourJsonFile.json

0

这里有一个使用 selectreducetostreamdelpaths 的解决方案。

map(  
    select(.name == "name1")
  | reduce (tostream|select(length==2)) as [$p,$v] (
      .
    ; if [$p[-1],$v] == ["name","name4"] then delpaths([$p[:-1]]) else . end
    )
)

0
我采用了与@peak类似的方法,但是将其反转,因此我们不是选择要输出的内容,而是选择不想要的内容并将其删除。
[path(.organizations[0].spaces[]| select(.name == "name4")] as $trash | delpaths($trash)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接