'Merge n input objects in jq

I have two JSON input files that I want to merge recursively:

file1.json

{
  "key1": {
    "key1.1": "foo",
    "key1.2": "bar"
  },
  "key2": {
    "key2.1": "daz"
  }
}

file2.json

{
  "key1": {
    "key1.3": "dingo"
  },
  "key2": {
    "key2.2": "lorem"
  }
}

I know I can combine these two with --slurp and the * operator:

jq --slurp '.[0] * .[1]' file1.json file2.json
{
  "key1": {
    "key1.1": "foo",
    "key1.2": "bar",
    "key1.3": "dingo"
  },
  "key2": {
    "key2.1": "daz",
    "key2.2": "lorem"
  }
}

And of course I can do this with any number of files, as long as I know the exact number of input files. However, how can the '.[0] * .[1]' part be generalised to work with an arbitrary number of input files?

For the + operator I could do '. | add', but + isn't what I want. Is there an equivalent to add for *?



Solution 1:[1]

jq --slurp '.[0] * .[1]' file1.json file2.json

Could be replaced with a reduce to match n files:

jq 'reduce inputs as $i (.; . * $i)' file1.json file2.json

To test this, lets add file3.json with the following content:

{
  "key7": {
    "key7.3": "dingo"
  },
  "key8": {
    "key8.2": "lorem"
  }
}

Changing the command to include a wildcard (*) (lazy...):

jq 'reduce inputs as $i (.; . * $i)' file*.json

Gives the following output:

{
  "key1": {
    "key1.1": "foo",
    "key1.2": "bar",
    "key1.3": "dingo"
  },
  "key2": {
    "key2.1": "daz",
    "key2.2": "lorem"
  },
  "key7": {
    "key7.3": "dingo"
  },
  "key8": {
    "key8.2": "lorem"
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 0stone0