Reputation: 1580
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":"[email protected]",
"events":[
{ "type":"open", "time":"t1", "ignore":"this" },
{ "type":"click", "time":"t2", "ignore":"this" } ] },
{ "email":"[email protected]",
"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":"[email protected]", "type":"open", "time":"t1" },
{ "email":"[email protected]", "type":"click", "time":"t2" },
{ "email":"[email protected]", "type":"open", "time":"t3" },
{ "email":"[email protected]", "type":"click", "time":"t4" },
{ "email":"[email protected]", "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?
Upvotes: 4
Views: 519
Reputation: 116740
Let's proceed in two steps: first, the (heavy) lifting, and secondly, the (light) trimming.
.emails | map( {email} + .events[])
or equivalently:
[.emails[] | {email} + .events[]]
Notice that {"email": .email}
has been abbreviated to {email}
.
We can delete the "ignore" key using del(.ignore)
. With an eye to efficiency, we arrive at the following solution:
.emails | map( {email} + (.events[] | del(.ignore) ) )
Upvotes: 2