with_entriesメソッドを使用してjqを介してキー名を再帰的に変更できますか?

with_entriesメソッドを使用してjqを介してキー名を再帰的に変更できますか?

次のJSONファイルがあるとします。

[
  {
    "name1": "fruits",
    "name2": "cars",
    "name3": "houses"
  }
]

jq次のように値の名前を変更するために使用できることがわかります。

jq '[.[] | .["newname1"] = .name1 | del(.name1)]' file

これはうまく機能し、より複雑なJSON構造でも変更できます...しかし、これは私が変更したいキーの非常に明確な説明です。同じタスクを実行する別の方法は、次のコマンドを使用することです。

jq 'map(with_entries(if .key == "name1" then .key = "newname1" else . end))' file 

JSON(オブジェクトの配列)内で特定の名前を持つすべてのキーを確認して変更する方法は次のとおりです。keyこの場合、明示的に宣言された名前は必要ありません。ただし、これはオブジェクトの配列にのみ適用されます。 json内のすべてのキーを再帰的に変更する方法を探したいと思います。次のJSONがあるとします。

{
  "name1": "one",
  "type": "FeatureCollection",
  "features": [
    {
      "name1": "one",
      "valueA": "0",
      "valueB": "0",
      "keyB": "2",
      "keyC": "3"
    },
    {
      "name1": "two",
      "valueA": "11",
      "valueB": "21",
      "keyB": "15",
      "keyC": "20"
    }
  ]
}

私の最後のjqコマンドはこのJSONでは機能しません。name1再帰を使用してすべてのキーを変更する方法はありますかjqrecurse(.[]?;true)そのコマンドの使い方を見つけることができますか?可能ですか?

答え1

jq 'walk(if type == "object" then with_entries( if .key == "name1" then .key = "newname1" else . end ) else . end)' file

jqこれはマニュアル(機能を説明する部分)からほぼそのまま出てきたものですwalk()。このwalk()関数は「再帰map()」のように動作します。注意すべき唯一のことは、現在処理中のエンティティの種類を確認することです。

を使用すると、walk()最初の方法を適用することもできます。

jq 'walk(if type == "object" and has("name1") then ( .newname1 = .name1 | del(.name1) ) else . end)' file

ただし、キーが見つかった場所を変更する代わりに(重要な場合)、newname1各オブジェクトの末尾にキーを配置します。name1

別のアプローチ(jq1.6)は、再帰的にまともな演算子を使用し..、探しているキーを持つオブジェクトを選択してからそのオブジェクトを更新することです。

jq '(.. | select(has("name1")?)) |= with_entries(if .key == "name1" then .key = "newname1" else . end)' file

関連情報