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)
與此命令一起使用的方法?可能嗎?
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