JQ Как объединить несколько объектов в один

С учетом следующего ввода (которое является уменьшенной версией вывода с 100K+ объектами другого сложного запроса):

echo '{ "a": { "b":"c", "d":"e" } }{ "a": { "b":"f", "d":"g" } }' | jq '.'
{
  "a": {
    "b": "c",
    "d": "e"
  }
}
{
  "a": {
    "b": "f",
    "d": "g"
  }
}

желаемый результат:

{
   "c": "e",
   "f": "g"
}

или (лучше подходит для последующего использования):

{
   x: {
      "c": "e",
      "f": "g"
   }
}

Я не могу на всю жизнь понять, как это сделать. Конечно же, моя настоящая проблема - это входные данные для нескольких объектов, для которых я действительно не знаю, является ли это действительным JSON. Jq производит и принимает его, Jshon нет. Я пробовал разные возможности, но ни один из них не дал того, что мне нужно. Я считал это наиболее вероятным кандидатом:

echo '{ "a": { "b":"c", "d":"e" } }{ "a": { "b":"f", "d":"g" } }' | jq ' . | { (.a.b): .a.d }'
{
   "c": "e"
}
{
   "f": "g"
}

Но увы. Другие вещи, которые я пробовал:

' . | { x: { (.a.b): .a.d } }'
'{ x: {} | . | add }'
'{ x: {} | . | x += }'
'{ x: {} | x += . }'
'x: {} | .x += { (.a.b): .a.d }'
'{ x: {} } | .x += { (.a.b): .a.d }'

Еще один, близкий, но без сигары

'reduce { (.a.b): .a.d } as $item ({}; . + $item)'
{
  "c": "e"
}
{
  "f": "g"
}

Кто хочет просветить меня?

Таким образом, полный ответ в приведенном выше случае использования, благодаря @peak,

echo '{ "a": { "b": "c", "d": "e" } }{ "a": { "b": "f", "d": "g" } }' | jq -n '{ x: [inputs | .a | { (.b): .d} ] | add }'
{
  "x": {
    "c": "e",
    "f": "g"
  }
}

1 ответ

Решение

Предположим, у вас есть jq 1.5 или более поздней версии и что ваши объекты JSON находятся в одном или нескольких файлах. Тогда для вашего первого ожидаемого результата вы можете просто написать:

[inputs | .a | { (.b): .d} ] | add

Это предполагает, что вы используете параметр командной строки -n. Я уверен, что как только вы увидите, насколько простое решение, дальнейшие объяснения будут излишними.

Для второго ожидаемого результата вы можете просто обернуть вышеупомянутую строку в:

{x: _}

Например:

$ jq -ncf program.jq input.json
{"x":{"c":"e","f":"g"}}

PS Ваш подход с использованием reduce это хорошо, но вам нужно использовать параметр командной строки -s.

pps Ты должен мне еще пива?

Другие вопросы по тегам