#json #merge #jq
#json #слияние #jq
Вопрос:
У меня есть 2 файла локали, и я хочу сгруппировать разные слова в один и тот же ключ
file1 en.json
{
"name": "Apple",
"error": {
"payment": {
"value1": "v1"
}
}
}
файл2 zh.json
{
"name": "orange",
"error": {
"payment": {
"value1": "v2",
"value2": "v5"
}
}
}
ожидаемый результат
{
"name": "Applenorange",
"error": {
"payment": {
"value1": "v1nv2",
"value2": "v5"
}
}
}
Я пытаюсь jq -s . en.json zh.json | jq '.[]'| jq -s
, но он не может объединяться по ключу.
{
"name": "orange",
"error": {
"payment": {
"value1": "v2",
"value2": "v5"
}
}
}
Комментарии:
1. Содержат ли ваши фактические входные данные поля с целочисленными / логическими значениями?
Ответ №1:
Насколько я понимаю, проблема, которую вы пытаетесь решить, заключается в том, что вы берете набор json, который соответствует некоторой структуре, и вы хотите собрать все значения, установленные на одном пути json, и создать объект с агрегированными значениями.
Для общего подхода, предполагающего, что в этой структуре не будет массивов, вы можете выделить все скалярные значения в наборе объектов (в этом помогут потоки), сгруппировать их по пути, а затем восстановить структуру объекта.
$ jq -n '
[inputs | tostream | select(length==2)] #1
| group_by(.[0]) #2
| map({
path: .[0][0],
values: [.[][1]]
}) #3
| reduce .[] as {$path, $values} (
{};
setpath($path; $values | join("n"))
) #4
' en.json zh.json
Обратите внимание на -n
флаг.
- Преобразует объекты в массив пар путь / значение из потока
- Группирует пары по пути
- Сопоставляет сгруппированные пары с чем-то более читаемым (не обязательно)
- Создает новый объект на основе группировок. Также принимает массив значений и объединяет их в виде одной
n
строки с разделителями. (как вам было нужно в ожидаемом результате)
Ответ №2:
Логика преобразования, которое вы имеете в виду, ускользает от меня, но, учитывая входные данные в вашем примере, следующее дает требуемый результат и может быть легко расширено различными способами:
jq -n '
input as $one
| input as $two
| reduce ($two | paths(scalars)) as $p ($one;
getpath($p) as $v
| ($two | getpath($p)) as $x
| if $v
then setpath($p; "($v)n($x)")
else setpath($p; $x)
end)
' en.json zh.json
Ответ №3:
Или аналогично, тот же запрос может быть выполнен с использованием jtc
— unix JSON processor:
bash $ <en.json jtc -mi zh.json / -w'<>i:' -u'<>i:' -T'"{$a}n{$b}"'
{
"error": {
"payment": {
"value1": "v1nv2",
"value2": "v5"
}
},
"name": "Applenorange"
}
— Первая цепочка ( -mi zh.json
) рекурсивно объединяет оба JSON;
— вторая цепочка ( -w'<>i:' -u'<>i:' -T'"{$a}n{$b}"'
) объединяет скаляры, полученные в результате слияния
PS. так получилось, что я также являюсь создателем jtc
.
PPS. вышеуказанный отказ от ответственности требуется SO.