
假設我有以下 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
到找到它的位置(如果這很重要)。
另一種方法(jq
1.6)是使用遞歸體面運算符..
,選擇具有我們正在尋找的密鑰的任何對象,然後更新這些對象:
jq '(.. | select(has("name1")?)) |= with_entries(if .key == "name1" then .key = "newname1" else . end)' file