
Допустим, у меня есть следующий 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) заключается в использовании рекурсивного оператора Decent ..
, выбирающего все, что имеет искомый нами ключ, а затем обновляющего эти объекты:
jq '(.. | select(has("name1")?)) |= with_entries(if .key == "name1" then .key = "newname1" else . end)' file