How to combine JSON objects with the same key, using jq
I have the following snippet exported as JSON:
{
"daisy": {
"dev": {
"app_url": "example.com",
"owner": "bob",
"createat": "2022-06-17T15:31:58Z",
}
}
}
{
"daisy": {
"dev": {
"appname": "daisy",
"flavor": [
"nodejs"
],
"file": "manifests/daisy.yml"
}
}
}
I would like to combine these objects into something like this:
{
"daisy": {
"dev": {
"app_url": "example.com",
"owner": "bob",
"createat": "2022-06-17T15:31:58Z",
"appname": "daisy",
"flavor": [
"nodejs"
],
"file": "manifests/daisy.yml"
}
}
}
How can I achieve this with jq
?
Multiplying two objects together will merge them. The following uses reduce
to successively build up a new object by merging the existing objects one by one.
Two similar ways to do this:
-
Using
-n
andinputs
withreduce
:jq -n 'reduce inputs as $item ({}; . *= $item)' file
This uses the
inputs
function, which returns the incoming objects one by one. This is combined with-n
(--null-input
) to disable the ordinary reading of inputs. -
Using
-s
and.[]
withreduce
:jq -s 'reduce .[] as $item ({}; . *= $item)' file
This reads the original data with
-s
(--slurp
) into an array, andreduce
is used to iterate over that array. Note that this is severely memory-inefficient and slow if the input is huge.
The result, given your data (and correcting it by removing a comma on the createat
line):
{
"daisy": {
"dev": {
"app_url": "example.com",
"owner": "bob",
"createat": "2022-06-17T15:31:58Z",
"appname": "daisy",
"flavor": [
"nodejs"
],
"file": "manifests/daisy.yml"
}
}
}
Note that if two or more objects share the same key and if that key refers to a scalar or array, then the later objects in the input will overwrite the value.