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

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

假設我有一個如下所示的 JSON:

{
    "key1": {
        "keyA": "1",
        "keyB": "null",
        "keyC": "null"
    },
    "key2": {
        "keyA": "null",
        "keyB": "3",
        "keyC": "null"
    }
}

我想找到一種方法來排除nullJSON 中具有值的所有鍵。所以結果如下:

{
    "key1": {
        "keyA": "1"
    },
    "key2": {
        "keyB": "3"
    }
}

我知道我可以使用 排除特定鍵及其名稱jq,例如cat myjson.json | jq 'del(.[]|.keyA)',這將刪除keyAjson 中的所有鍵,但我想根據它們的值排除鍵...如何使用 排除所有具有值的"null"jq

答案1

del(..|select(. == "null"))

這使用了遞歸下降運算符..select功能尋找物件中任何位置的所有位置,其值等於"null"並將它們賦予delselect評估布林表達式來決定是否包含特定值,同時..將樹中的每個值賦予它,並del接受任何生成位置的表達式,這就是這樣做的。 (示範

您可以使用該path函數來檢查它發現了什麼:

path(..|select(. == "null"))

並調試它認為您要首先嘗試刪除的內容。這輸出是一個鍵數組,要遞歸地達到該值,因此數組中的最後一項是實際要刪除的鍵。

您也可以在 jq 1.6 及更高版本中使用更新分配|= empty(在早期版本中它會默默地失敗)。您可能會或可能不會發現這一點更清楚(..|select(. == "null")) |= empty:(示範) 刪除那些相同的鍵。


如果您的值是 true null,而不是 string "null",您可以使用nulls內建函數來取代整個select: del(..|nulls)

如果您的值是 true null你正在使用傑q 1.5(許多發行版中的當前版本),您需要使用 來recurse(.[]?; true)代替...這是因為空值被明確排除在外..(因為它被定義為recurse, 哪個定義為 recurse(.[]?),其定義為recurse(.[]?; . != null))。不過,這種行為在 1.6 中改為上面的(更有用的)行為文件沒有改變,這似乎是個文檔錯誤

答案2

假設您知道要測試第二級的值:

jq 'del(.[][] | select(. == "null"))' file

這會刪除從頂部開始的第二層上的每個鍵值對,其中值是文字 string null

鑑於問題中的文檔,這會產生預期的輸出。

使用高於 1.5 的版本jq,您也可以將資料更新為沒有該null值的位元:

jq '.[][] |= select(. != "null")' file

相關內容