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)'これにより json 内のすべてのキーが消去されますが、値に応じてキーを除外したいのです...を使用してkeyA値を持つすべてのキーを除外するにはどうすればよいですか?"null"jq

答え1

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

これは、再帰下降演算子..そしてselect関数は、オブジェクト内の任意の場所で に等しい値を持つすべての場所を検索し"null"、 に渡しますdelselectはブール式を評価して特定の値を含めるかどうかを決定し、 は..ツリー内のすべての値をそれに渡し、del場所を生成する任意の式を受け入れます。これはこれを実行します。(デモ

関数を使用してpath、何が見つかったかを確認できます。

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

まず何を削除しようとしているのかデバッグします。出力値に到達するために再帰的にたどるキーの配列であり、配列の最後の項目が実際に削除されるキーになります。

jq 1.6 以降では update-assignment も使用できます|= empty(以前のバージョンでは何も表示されずに失敗します)。これはより明確になるかもしれませんし、そうでないかもしれません: (..|select(. == "null")) |= empty(デモ) は同じキーを削除します。


値がnull文字列ではなく true である場合は、全体の代わりに組み込み関数を使用"null"できます。nullsselectdel(..|nulls)

値が真のヌルの場合そして使用しているjq 1.5(多くのディストリビューションの現在のバージョン)では、recurse(.[]?; true)の代わりにを使用する必要があります..。これは、null値が明示的に除外されるためです..それは次のように定義されますrecurse、 どれのと定義されている recurse(.[]?)(これは と定義されますrecurse(.[]?; . != null))。この動作は1.6で上記の(より便利な)動作に変更されましたが、ドキュメント変わっていない、それはドキュメントのバグのようです

答え2

2 番目のレベルで値をテストする必要があると仮定します。

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

これにより、上から 2 番目のレベルにある、値がリテラル文字列であるすべてのキーと値のペアが削除されますnull

質問内のドキュメントが与えられれば、期待通りの出力が生成されます。

1.5 より新しいバージョンを使用するとjq、値を持たないビットにデータを更新することもできますnull

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

関連情報