jq: Lifting fields from array of objects into the parent object

  • 0
  • Pump00:00

I have a JSON object an array at the top-level, and each array entry is an object with a nested array of objects as one of the fields.
I’d like to “lift” some fields from the sub-arrays into the objects within the first array. It’s confusing to write, so, here’s my input:

{ "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" } ] }
] }

What I’d like to receive as output is:

[
  { "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" }
]

I can jq this with multiple pipes already, like so:

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

… but this seems way too verbose.
Is there an easier way to ‘lift’ those type and time fields from the deepest objects to the object one-level up?
When I try to use the .events[] iterator twice, I wind up with the Cartesian product of events, which is wrong :-/

I must be missing some simpler way (than my ‘intermediate-object’ approach above) to achieve this … anyone know of a better way?

Default Asked on February 4, 2020 in Programming.
Add Comment
  • 0 Answer(s)
  • Your Answer

    By posting your answer, you agree to the privacy policy and terms of service.