Dror Dror - 1 month ago 19
JSON Question

Flatten a JSON document using jq

I'm considering the following array of JSON objects:

[
{
"index": "index1",
"type": "type1",
"id": "id1",
"fields": {
"deviceOs": [
"Android"
],
"deviceID": [
"deviceID1"
],
"type": [
"type"
],
"country": [
"DE"
]
}
},
{
"index": "index2",
"type": "type2",
"id": "id2",
"fields": {
"deviceOs": [
"Android"
],
"deviceID": [
"deviceID2"
],
"type": [
"type"
],
"country": [
"US"
]
}
}
]


and I would like to flatten it to get:

[
{
"index": "index1",
"type": "type",
"id": "id1",
"deviceOs": "Android",
"deviceID": "deviceID1",
"country": "DE"
},
{
"index": "index2",
"type": "type",
"id": "id2",
"deviceOs": "Android",
"deviceID": "deviceID2",
"country": "US"
}
]


I'm trying to work with
jq
but I fail to flatten the
"fields"
. How should I do it? At the moment I'm interested in command-line tools, but I'm open to other suggestions as well.

Answer

This one was a tricky one to craft.

map
(
    with_entries(select(.key != "fields"))
    +
    (.fields | with_entries(.value = .value[0]))
)

Let's break it down and explain the bits of it

  1. For every item in the array...

    map(...)
    
  2. Create a new object containing the values for all except the fields property.

    with_entries(select(.key != "fields"))
    
  3. Combine that with...

    +
    
  4. Each of the fields projecting each of the values to the first item of each array

    (.fields | with_entries(.value = .value[0]))