
Digamos que eu tenha o seguinte arquivo JSON:
[
{
"name1": "fruits",
"name2": "cars",
"name3": "houses"
}
]
Eu sei que posso usar jq
para renomear seus valores como o seguinte:
jq '[.[] | .["newname1"] = .name1 | del(.name1)]' file
Isso funciona bem e me permite fazer alterações mesmo em estruturas JSON mais complexas... No entanto, essa é uma declaração muito explícita das chaves que desejo alterar. Uma maneira alternativa de fazer a mesma coisa seria com o comando:
jq 'map(with_entries(if .key == "name1" then .key = "newname1" else . end))' file
Esta é uma forma de verificar todas as chaves com nomes específicos dentro de um JSON que é um Array de Objetos e alterá-las. Não preciso declarar explicitamente o nome do key
neste caso. No entanto, isso funciona apenas em uma matriz de objetos. Eu gostaria de encontrar uma maneira de alterar todas as chaves dentro de um JSON assim de forma recursiva. Digamos que eu tenha um JSON como este:
{
"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"
}
]
}
Meu último jq
comando não funciona neste JSON. Existe alguma maneira de alterar todas name1
as chaves recursivamente usando jq
? Talvez encontrando uma maneira de usar recurse(.[]?;true)
junto com este comando? É possível?
Responder1
jq 'walk(if type == "object" then with_entries( if .key == "name1" then .key = "newname1" else . end ) else . end)' file
Isso vem mais ou menos direto do jq
manual (a seção que descreve a walk()
função). A walk()
função atua como uma "recursiva map()
" e a única coisa que precisamos ter cuidado é verificar o tipo de entidade com a qual estamos lidando atualmente.
Usando walk()
, você também pode aplicar a sua primeira abordagem:
jq 'walk(if type == "object" and has("name1") then ( .newname1 = .name1 | del(.name1) ) else . end)' file
No entanto, isso coloca a newname1
chave por último em cada objeto, em vez de substituí-la name1
na posição onde foi encontrada (se isso for importante).
Outra abordagem (com jq
1.6) é usar o operador decente recursivo ..
, selecionando qualquer coisa que tenha a chave que procuramos e, em seguida, atualizando esses objetos:
jq '(.. | select(has("name1")?)) |= with_entries(if .key == "name1" then .key = "newname1" else . end)' file