jq: перенос полей из массива объектов в родительский объект - PullRequest
0 голосов
/ 14 января 2019

У меня есть объект JSON - массив на верхнем уровне, и каждая запись массива - это объект с вложенным массивом объектов в качестве одного из полей. Я хотел бы «поднять» некоторые поля из подмассивов в объекты в первом массиве. Это сбивает с толку, чтобы написать, так что вот мой ввод:

{ "emails": [
  { "email":"foo1@bar.com",
    "events":[
      { "type":"open", "time":"t1", "ignore":"this" },
      { "type":"click", "time":"t2", "ignore":"this" } ] },
  { "email":"foo2@bar.com",
    "events":[
      { "type":"open", "time":"t3", "ignore":"this" },
      { "type":"click", "time":"t4", "ignore":"this" },
      { "type":"open", "time":"t5", "ignore":"this" } ] }
] }

Что я хотел бы получить в качестве вывода:

[
  { "email":"foo1@bar.com", "type":"open", "time":"t1" },
  { "email":"foo1@bar.com", "type":"click", "time":"t2" },
  { "email":"foo2@bar.com", "type":"open", "time":"t3" },
  { "email":"foo2@bar.com", "type":"click", "time":"t4" },
  { "email":"foo2@bar.com", "type":"open", "time":"t5" }
]

Я могу jq это уже с несколькими трубами, вот так:

 [ .emails[] | { email:.email, event:(.events[] | { type:.type, time:.time }) } | { email:.email, type:.event.type, time:.event.time } ]

... но это кажется слишком многословным. Есть ли более простой способ «поднять» эти поля type и time с самых глубоких объектов на один уровень выше? Когда я пытаюсь использовать итератор .events[] дважды, я получаю декартово произведение событий, что неверно: - /

Я, должно быть, упускаю какой-то более простой способ (чем мой подход «промежуточный объект» выше), чтобы достичь этого ... кто-нибудь знает лучший способ?

1 Ответ

0 голосов
/ 14 января 2019

Давайте продолжим в два этапа: во-первых, (тяжелый) подъем, а во-вторых, (легкий) обрезка.

Подъем

.emails | map( {email}  + .events[])

или эквивалентно:

[.emails[] | {email}  + .events[]]

Обратите внимание, что {"email": .email} было сокращено до {email}.

Обрезка

Мы можем удалить ключ игнорирования, используя del(.ignore). С целью повышения эффективности мы приходим к следующему решению:

.emails | map( {email}  + (.events[] | del(.ignore) ) )
...