#json #parent-child #jq
#json #родитель-потомок #jq
Вопрос:
Я пытаюсь понять, каков наилучший способ добавить элемент json к родительскому элементу дочернего элемента, если этот дочерний элемент содержит определенный ключ: значение, и, наконец, распечатать весь json с помощью jq, который я пытаюсь лучше объяснить на примере. Входной json является:
{
"family": {
"surname": "Smith"
},
"components": [
{
"name": "John",
"details": {
"hair": "brown",
"eyes": "brown",
"age": "56"
},
"role": "father"
},
{
"name": "Mary",
"details": {
"hair": "blonde",
"eyes": "green",
"age": "45"
},
"role": "mother"
},
{
"name": "George",
"details": {
"hair": "blonde",
"eyes": "brown",
"age": "25"
},
"role": "child"
}
]
}
Я хочу добавить:
«описание»: «на 5 лет меньше 30»
на том же уровне «сведений», если «возраст» равен «25», а затем распечатайте результат:
{
"family": {
"surname": "Smith"
},
"components": [
{
"name": "John",
"details": {
"hair": "brown",
"eyes": "brown",
"age": "56"
},
"role": "father"
},
{
"name": "Mary",
"details": {
"hair": "blonde",
"eyes": "green",
"age": "45"
},
"role": "mother"
},
{
"name": "George",
"details": {
"hair": "blonde",
"eyes": "brown",
"age": "25"
},
"role": "child",
"description": "5 years less than 30"
}
]
}
Единственным решением, которое я нашел, было применить обновление, но напечатать только содержимое «компонентов»;
затем я удалил из JSON и, наконец, вставил измененное содержимое «компонентов», ранее сохраненное таким образом:
cat sample.json | jq -c ' .components[] | select(.details.age=="25") |= . {description: "5 years less than 30" } ' > /tmp/saved-components.tmp
cat sample.json | jq --slurpfile savedcomponents /tmp/saved-components.tmp 'del(.components) | . { components: [ $savedcomponents ] }'
Я не думаю, что это лучший способ решения проблем такого рода, поэтому я хотел бы знать, что такое
правильный «подход jq».
Я забыл сказать: я предпочитаю использовать только jq, а не другие инструменты
Чем вы
Марко
Ответ №1:
Вы можете выбрать объект, соответствующий условию, и добавить к этому объекту. Что-то вроде приведенного ниже. Ключ в том, чтобы использовать =
назначение модификации, чтобы не потерять другие объекты
(.components[] | select(.details.age == "25")) = { "description": "5 years less than 30" }
Комментарии:
1. Спасибо, ваши решения и @peak работают очень хорошо; Я бы хотел установить для обоих значение accepted solution, но я не знаю, как это сделать. Я попытался повторить ваше решение следующим образом:
cat sample.json | jq '(.components[] | select(.details.age == "25")) = { "description": "5 years less than 30" }' | jq '(.components[] | select(.details.age == "25")) = { "description": "under 30" }'
и я ожидал увидеть два ключа описания, но я вижу только последнее обновление. Это функция jq, которая не допускает дублирования ключей, или операция » =»?2. jq позволяет указывать повторяющиеся ключи, но обычно игнорирует все, кроме последнего. («Обычно», потому что это неверно, когда действует «потоковый анализатор» (включен с помощью —stream).)
Ответ №2:
Вот простое («без волшебства») и эффективное решение:
.components |=
map(if .details.age=="25" then .description = "5 years less than 30" else . end)