I've got a more complex JQ expression that's handling an array of objects.
The input looks like this:
[
{ "key": "1", "value": "value 1"},
{ "key": "2", "value": "value 2"},
{ "key": "1", "value": "value 3"},
]
What I want to get is this:
{
"1": { "values": ["value 1", "value 3"] },
"2": { "values": ["value 2"] }
}
or, for my use case:
{
"1": [ "value 1", "value 3" ],
"2": [ "value 2" ]
}
would also be OK.
I've already tried to use … | { (.key): [.value] }
but the result is (to no real surprise to me) that later occurrences of keys simply overwrite already existing ones. What I want to accomplish is something like "create a new key/value pair or add .value to an already existing one's 'values' array".
The drawback of a solution relying on group_by
is that group_by
requires a sort, which is unnecessary here. In this response, I'll show how to avoid any sorting by using a generic (and generally useful) jq function that "melds" an array of JSON objects, essentially by popping the value at each key into an array, and then concatenating corresponding arrays.
# input should be an array of objects
def meld:
reduce .[] as $o
({}; reduce ($o|keys)[] as $key (.; .[$key] += [$o[$key]] ));
Let's also define some data:
def data:
[
{ "key": "1", "value": "value 1"},
{ "key": "2", "value": "value 2"},
{ "key": "1", "value": "value 3"}
]
;
Then the filter:
data | map([.] | from_entries) | meld
produces:
{"1":["value 1","value 3"],"2":["value 2"]}
OK, after finally finding out what I wanted I also understand that my previous filters didn't keep the input array but resulted in objects being output after each other. So that was basically the reason why all examples I found wouldn't work.
I wanted to group by keys (hence the key/value requirement), which group_by already does, but wouldn't work.
From grouping working its only a small step to my solution (unique keys, values in arrays).
'… group_by(.key) | map({ "key": .[0].key, "values": map(.value) | unique })'
The output now looks like this, which is perfectly fine for my requirements:
[
{
"key": "1",
"values": [
"value 1",
"value 3"
],
},
{
"key": "2",
"values": [
"value 2"
]
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With