如何使用 jq 在 JSON 中排除具有特定值的所有键?

ray*_*ght 4 jq

假设我有一个如下所示的 JSON:

{
    "key1": {
        "keyA": "1",
        "keyB": "null",
        "keyC": "null"
    },
    "key2": {
        "keyA": "null",
        "keyB": "3",
        "keyC": "null"
    }
}
Run Code Online (Sandbox Code Playgroud)

我想找到一种方法来排除所有具有nullJSON值的键。所以结果如下:

{
    "key1": {
        "keyA": "1"
    },
    "key2": {
        "keyB": "3"
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用它们的名字排除特定的键jq,例如cat myjson.json | jq 'del(.[]|.keyA)',这将删除我keyA在 json 中的所有键,但我想根据它们的值排除这些键......如何"null"使用排除所有具有值的键jq

Mic*_*mer 8

del(..|select(. == "null"))
Run Code Online (Sandbox Code Playgroud)

这使用递归下降运算符..select函数来查找对象中任何位置的所有位置,其值等于"null"并将它们赋予delselect计算布尔表达式以决定是否包含特定值,同时..将树中的每个值都提供给它,并del接受任何产生位置的表达式,这是这样做的。(演示

您可以使用该path函数来检查它发现了什么:

path(..|select(. == "null"))
Run Code Online (Sandbox Code Playgroud)

并调试它认为您首先要删除的内容。该输出是按键阵列遵循递归为达到值,所以数组中的最后一个项目是,实际上被删除的关键。

您还可以|= empty在 jq 1.6 及更高版本中使用更新分配(它在早期版本中默默地失败)。您可能会或可能不会发现这个清晰的:(..|select(. == "null")) |= empty演示)删除那些相同的密钥。


如果您的值是 true nulls,而不是 string "null",则可以使用nulls内置函数代替整个select: del(..|nulls)

如果你的价值观是真正的空你使用JQ 1.5(当前版本中许多发行),你需要使用recurse(.[]?; true)的地方..。这是因为空值被明确排除在外..(因为它定义为recurse定义为 recurse(.[]?),定义为recurse(.[]?; . != null))。这种行为在 1.6 中变成了上面的(更有用的)行为,尽管文档没有改变,这似乎是一个文档错误

  • @raylight 如果您运行的是 jq 1.5,则 `..` *排除* true null 值。您可以将 `..` 替换为 [`recurse(.[]?;true)`](https://stedolan.github.io/jq/manual/v1.5/#recurse(f),recurse,recurse( f;condition),recurse_down) 并且它应该可以工作 - `..` 在 1.6 中工作(尽管文档实际上仍然[说](https://stedolan.github.io/jq/manual/v1.6/#RecursiveDescent: ..)它[不应该](https://stedolan.github.io/jq/manual/#recurse(f),recurse,recurse(f;condition),recurse_down))。您还可以将 select(.==null) 简化为内置的 nulls 。 (2认同)