Вопрос или проблема
У меня есть первая структура json. Все значения всегда равны null.
{
"A": {
"A1": {
"A11": null,
"A12": null
}
},
"B": {
"B1": {
"B12": null
},
"B2": null
},
"C": {
"C1": {
"C11": null,
"C12": null
},
"C2" : {
"C21": {
"C211": null
}
}
}
}
Во второй структуре json все значения всегда являются строками.
{
"A": {
"A1": {
"A11": "valueA11",
}
},
"B": {
"B1": {
"B12": "valueB12",
"B13": "valueB13"
},
"B2": "valueB2"
},
"C": "valueC"
}
Результат будет таким:
{
"A": {
"A1": {
"A11": "valueA11",
"A12": null
}
},
"B": {
"B1": {
"B12": "valueB12"
},
"B2": "valueB2"
},
"C": {
"C1": {
"C11": null,
"C12": null
},
"C2" : {
"C21": {
"C211": null
}
}
}
}
Как мне заполнить ключи первого json значениями из второго, если ключи существуют во втором json, в противном случае мы оставляем значения null?
Я пытался использовать jq в bash, но без успеха. Я готов использовать любой инструмент, который справится с задачей.
Итерация с помощью reduce
по путям из paths(. == null)
, получение соответствующего значения во втором input
с использованием getpath
, и установка его с помощью setpath
или возвращение к текущему значению итерации с помощью ? // .
.
jq 'input as $in |
reduce paths(. == null) as $p (.; setpath($p; $in | getpath($p))? // .)
' first.json second.json
{
"A": {
"A1": {
"A11": "valueA11",
"A12": null
}
},
"B": {
"B1": {
"B12": "valueB12"
},
"B2": "valueB2"
},
"C": {
"C1": {
"C11": null,
"C12": null
},
"C2": {
"C21": {
"C211": null
}
}
}
}
Ответ или решение
Для решения задачи по объединению двух JSON-структур с использованием утилиты jq
, мы можем воспользоваться подходом, который позволяет заполнять значения из второго JSON в первом, если ключи совпадают. В первом JSON все значения равны null
, а во втором – это строки. Наша цель – обновить первый JSON, сохраняя структуру объектов и заполняя только те ключи, которые имеют соответствия во втором JSON.
Исходные JSON-структуры выглядят следующим образом:
Первый JSON (ключи с null
значениями):
{
"A": {
"A1": {
"A11": null,
"A12": null
}
},
"B": {
"B1": {
"B12": null
},
"B2": null
},
"C": {
"C1": {
"C11": null,
"C12": null
},
"C2": {
"C21": {
"C211": null
}
}
}
}
Второй JSON (ключи со строковыми значениями):
{
"A": {
"A1": {
"A11": "valueA11"
}
},
"B": {
"B1": {
"B12": "valueB12",
"B13": "valueB13"
},
"B2": "valueB2"
},
"C": "valueC"
}
Результатом, который вы ожидаете получить, будет:
{
"A": {
"A1": {
"A11": "valueA11",
"A12": null
}
},
"B": {
"B1": {
"B12": "valueB12"
},
"B2": "valueB2"
},
"C": {
"C1": {
"C11": null,
"C12": null
},
"C2": {
"C21": {
"C211": null
}
}
}
}
Чтобы добиться такого результата, вы можете использовать следующую команду на bash
с утилитой jq
:
jq 'input as $in |
reduce paths(. == null) as $p (.; setpath($p; $in | getpath($p))? // .)' first.json second.json
Объяснение команды:
input as $in
– сохраняем второй JSON во временную переменную$in
.reduce paths(. == null) as $p
– проходим по всем путям в первом JSON, где значение равноnull
.setpath($p; $in | getpath($p))? // .
– для каждого найденного пути$p
, пытаемся установить значение из второго JSON (если оно существует), и если его нет, оставляем текущее значение (то естьnull
).
Таким образом, данный подход позволяет элегантно и эффективно объединять обе структуры, сохраняя при этом необходимые значения и структуру первого JSON.
Для тестирования и демонстрации данного решения, можете воспользоваться данной ссылкой на jqPlay.