#json #bash #merge #key #jq
#json #bash #объединить #Клавиша #jq
Вопрос:
У меня есть 2 объекта json в 2 переменных V1 и V2.
V1 — это
{
"Parameters: {
"a": "value-of-a",
"b": "value-of-b"
}
}
V2 — это
{
"Parameters": {
"a": "new-value-of-a",
"c": "value-of-c"
}
}
Я хочу переопределить значения V1 значениями из V2. Я хочу сгенерировать новый JSON, который выглядит следующим образом:
Ожидаемый
{
"Parameters": {
"a": "new-value-of-a",
"b": "value-of-b"
}
}
Я попробовал следующее:
(
echo '{ "Parameters": { "a": "value-of-a", "b": "value-of-b" } }'
'{ "Parameters": { "a": "new-value-of-a", "c": "value-of-c" } }'
| jq --slurp 'reduce .[] as $item ({}; . * $item)'
)
но это генерирует
Актуально
{
"Parameters": {
"a": "new-value-of-a",
"b": "value-of-b",
"c": "value-of-c"
}
}
Проблема в том, что я не хочу, чтобы в результате отображались узлы в версии V2, которых нет в версии V1. Кто-нибудь может мне помочь?
Ответ №1:
Вот решение без сокращения, которое концептуально просто и хорошо масштабируется:
jq -n '
# Emit the object with key-value pairs of $o2
# for keys that appear in both . and $o2
def commonKeys($o2):
keys_unsorted as $k1
| ($o2|keys_unsorted) as $k2
| [($k1 - ($k1-$k2))[] | {(.): $o2[.]}] | add
;
input.Parameters as $dict
| input
| .Parameters |= (. commonKeys($dict))
' v2.json v1.json
Ответ №2:
Если $.Parameter
объект прост, как в вашем примере
jq
--argjson a '{ "Parameters": { "a": "value-of-a", "b": "value-of-b" } }'
--argjson b '{ "Parameters": { "a": "new-value-of-a", "c": "value-of-c" } }'
-n '
$a | .Parameters | keys_unsorted as $whitelist
| $b | .Parameters | with_entries( select(.key | IN($whitelist[])) ) as $update
| $a | .Parameters = $update '
Если у вас есть два файла, вы могли бы (например) использовать input
twice вместо --argjson
.
Комментарии:
1. Андрей, большое спасибо, что нашли время ответить на мой вопрос! Ценю это! Я был так далеко… Я вижу, что со статическими значениями это работает. Однако, как только я переключаюсь на —slurpfile, я получаю следующую ошибку: невозможно индексировать массив с помощью строки «Параметры» . Как это следует изменить, чтобы использовать —slurpfile ?
2. Я просто изменил сценарий, чтобы использовать —argfile вместо —slurpfile, и он работал просто отлично. Андрей, еще раз спасибо за вашу помощь! Ты спас мой день!
Ответ №3:
Вот простое и эффективное решение:
jq -n '
input.Parameters as $dict
| input
| .Parameters |= reduce keys_unsorted[] as $k (.;
if ($dict|has($k)) then .[$k] = $dict[$k] else . end)
' v2.json v1.json
Если два значения являются переменными оболочки, вы можете использовать --argjson
или просто повторить их:
echo "$v2" "$v1" | jq -n '...'
Существуют и другие способы предоставления двух значений, но в целом лучше избегать параметра командной строки -s.
Комментарии:
1.
input
пытается прочитать одно значение JSON без какого-либо возврата. См. Руководство по jq stedolan.github.io/jq/manual