是否可以使用 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使用遞歸更改所有鍵jq?也許找到一種recurse(.[]?;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

相關內容