Объединение одного атрибута JSON из нескольких в один файл с использованием jq - PullRequest
3 голосов
/ 30 января 2020

У меня есть несколько JSON файлов одинаковой формы, вот два примера:

message_1. json

{
  "participants": [
    {
      "name": "Person One"
    },
    {
      "name": "Person Two"
    }
  ],

  "messages": [
    {
      "sender_name": "Person One",
      "timestamp_ms": 0002,
      "content": "Text2.",
      "type": "Generic"
    },
    {
      "sender_name": "Person Two",
      "timestamp_ms": 0001,
      "content": "Text1.",
      "type": "Generic"
    }
  ],
  "title": "Person One",
  "is_still_participant": true,
  "thread_type": "Regular",
  "thread_path": "inbox/SomeString"
}

message_2. json

{
  "participants": [
    {
      "name": "Person One"
    },
    {
      "name": "Person Two"
    }
  ],

  "messages": [
    {
      "sender_name": "Person Two",
      "timestamp_ms": 0004,
      "content": "Text4.",
      "type": "Generic"
    },
    {
      "sender_name": "Person One",
      "timestamp_ms": 0003,
      "content": "Text3.",
      "type": "Generic"
    }
  ],
  "title": "Person One",
  "is_still_participant": true,
  "thread_type": "Regular",
  "thread_path": "inbox/SomeString"
}

Можно ли использовать jq для объединения файлов JSON, чтобы атрибут messages был объединен (порядок не имеет значения), а остальные остались одни?

Результат слияния message_1. json и message_2. json будет выглядеть следующим образом:

messages. json

{
  "participants": [
    {
      "name": "Person One"
    },
    {
      "name": "Person Two"
    }
  ],

  "messages": [
    {
      "sender_name": "Person One",
      "timestamp_ms": 0002,
      "content": "Text2.",
      "type": "Generic"
    },
    {
      "sender_name": "Person Two",
      "timestamp_ms": 0001,
      "content": "Text1.",
      "type": "Generic"
    },
    {
      "sender_name": "Person Two",
      "timestamp_ms": 0004,
      "content": "Text4.",
      "type": "Generic"
    },
    {
      "sender_name": "Person One",
      "timestamp_ms": 0003,
      "content": "Text3.",
      "type": "Generic"
    }
  ],
  "title": "Person One",
  "is_still_participant": true,
  "thread_type": "Regular",
  "thread_path": "inbox/SomeString"
}

У меня 11 JSON файлов, message_1 . json, ..., message_11. json. Я хотел бы объединить их в один messages.json файл этой формы, содержащий все сообщения в файлах JSON. Как я могу сделать это, используя jq через bash?

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Вот один из подходов, который имеет то преимущество, что не требует опции -s, которая потребляет больше памяти, чем необходимо:

jq 'reduce inputs as $in (.;
  .messages += $in.messages)
' $(for i in $(seq 1 11); do echo message_$i.json ; done)

Обратите внимание, что в этом случае jq должен вызываться без опция -n.

0 голосов
/ 30 января 2020

В одном случае, используя режим slurp, который помещает все содержимое файлов JSON в один массив, а затем обрабатывает его, добавляя все сообщения других объектов к первому в этом массиве:

$  jq -s 'reduce .[1:][] as $m (.[0]; .messages += $m.messages)' message_*.json
{
  "participants": [
    {
      "name": "Person One"
    },
    {
      "name": "Person Two"
    }
  ],
  "messages": [
    {
      "sender_name": "Person One",
      "timestamp_ms": 2,
      "content": "Text2.",
      "type": "Generic"
    },
    {
      "sender_name": "Person Two",
      "timestamp_ms": 1,
      "content": "Text1.",
      "type": "Generic"
    },
    {
      "sender_name": "Person Two",
      "timestamp_ms": 4,
      "content": "Text4.",
      "type": "Generic"
    },
    {
      "sender_name": "Person One",
      "timestamp_ms": 3,
      "content": "Text3.",
      "type": "Generic"
    }
  ],
  "title": "Person One",
  "is_still_participant": true,
  "thread_type": "Regular",
  "thread_path": "inbox/SomeString"
}
...