Как слить 2 json файл с помощью jq?
Я использую jq инструменты (jq-json-processor) в оболочке script для разбора json.
У меня есть 2 json файла и хотят объединить их в один уникальный файл
Здесь содержимое файлов:
file1
{
"value1": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value1": "v1",
"value2": "v2"
},
"bbb": {
"value1": "v1",
"value2": "v2"
},
"ccc": {
"value1": "v1",
"value2": "v2"
}
}
}
file2
{
"status": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value3": "v3",
"value4": 4
},
"bbb": {
"value3": "v3"
},
"ddd": {
"value3": "v3",
"value4": 4
}
}
}
ожидаемый результат
{
"value": {
"aaa": {
"value1": "v1",
"value2": "v2",
"value3": "v3",
"value4": 4
},
"bbb": {
"value1": "v1",
"value2": "v2",
"value3": "v3"
},
"ccc": {
"value1": "v1",
"value2": "v2"
},
"ddd": {
"value3": "v3",
"value4": 4
}
}
}
Я стараюсь много комбинировать, но единственный результат, который я получаю, следующий: это не ожидаемый результат:
{
"ccc": {
"value2": "v2",
"value1": "v1"
},
"bbb": {
"value2": "v2",
"value1": "v1"
},
"aaa": {
"value2": "v2",
"value1": "v1"
}
}
{
"ddd": {
"value4": 4,
"value3": "v3"
},
"bbb": {
"value3": "v3"
},
"aaa": {
"value4": 4,
"value3": "v3"
}
}
С помощью этой команды:
jq -s '.[].value' file1 file2
Ответы
Ответ 1
Начиная с 1.4, теперь это возможно с оператором *
. При задании двух объектов он будет регрессировать их. Например,
jq -s '.[0] * .[1]' file1 file2
Вы получите:
{
"value1": 200,
"timestamp": 1382461861,
"value": {
"aaa": {
"value1": "v1",
"value2": "v2",
"value3": "v3",
"value4": 4
},
"bbb": {
"value1": "v1",
"value2": "v2",
"value3": "v3"
},
"ccc": {
"value1": "v1",
"value2": "v2"
},
"ddd": {
"value3": "v3",
"value4": 4
}
},
"status": 200
}
Если вы также хотите избавиться от других ключей (например, ожидаемого результата), один из способов сделать это:
jq -s '.[0] * .[1] | {value: .value}' file1 file2
Или, предположительно, несколько более эффективный (поскольку он не объединяет никаких других значений):
jq -s '.[0].value * .[1].value | {value: .}' file1 file2
Ответ 2
Используйте jq -s add
:
$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
"a": 0,
"b": "bar",
"c": "baz"
}
Это считывает все тексты JSON из stdin в массив (jq -s
делает это), затем он "уменьшает" их.
(add
определяется как def add: reduce .[] as $x (null; . + $x);
, который выполняет итерацию по значениям входного массива/объекта и добавляет их. Добавление объекта == merge.)
Ответ 3
Кто знает, если вам все еще нужно, но вот решение.
Как только вы перейдете к опции --slurp
, это легко!
--slurp/-s:
Instead of running the filter for each JSON object in the input,
read the entire input stream into a large array and run the filter just once.
Затем оператор +
сделает то, что вы хотите:
jq -s '.[0] + .[1]' config.json config-user.json
(Примечание: если вы хотите объединить внутренние объекты, а не просто переписать левый файл с нужными файлами, вам нужно будет сделать это вручную)
Ответ 4
Здесь версия, которая работает рекурсивно (используя *
) на произвольном числе объектов:
echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)'
{
"A": {
"a": 1,
"b": 2
},
"B": 3
}
Ответ 5
Во-первых, { "значение":.value} может быть сокращено до просто значения {.}.
Во-вторых, может быть интересен параметр -argfile (доступен в jq 1.4 и jq 1.5), поскольку он избегает использования опции -slurp.
Объединяя их, два объекта в двух файлах могут быть объединены следующим образом:
$ jq --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'