jsonmergejq

in jq, how to merge an array of object into 1 object with an array of values


Let's say I have this json:

[
  {
    "first": 12355,
    "second": "abc"
  },
  {
    "first": 89010,
    "second": "def"
  },
  {
    "first": 23423,
    "second": "hij"
  },
  {
    "first": 23456,
    "second": "klm"
  },
  {
    "first": 11111,
    "second": "nop"
  }
]

And I would like (a generic form) that merges them into 1 object where the value of each key is merged into an array of the corresponding values:

{
    "first" : [12355,89010,23423,23456,11111],
    "second" : ["abc","def","hij","klm","nop"]
}

I was trying this, but it produces no output at all.

reduce .[] as $final (
    {};
    ((. | keys) as $k |
        map(
            ( (.[$k] // []) += ($final[$k] // []))
        )
    )
)

Solution

  • I'd use to_entries (to access keys and values) as part of the iteration:

    reduce (.[] | to_entries[]) as $e ({}; .[$e.key] += [$e.value])
    

    Demo

    Here's another way using group_by to bring the matching items together:

    map(to_entries[]) | group_by(.key) | map({(first.key): map(.value)}) | add
    

    Demo

    Output:

    {
      "first": [
        12355,
        89010,
        23423,
        23456,
        11111
      ],
      "second": [
        "abc",
        "def",
        "hij",
        "klm",
        "nop"
      ]
    }