'jq - apply modifications from a file

I have some json content in a file: content.json

{
  "Type": {
    "OS": "Windows"
  },
  "Network": {
     "Protocol": "unknown",
     "Port": 80
  }
}

And some json updates in a file: updates.json

{
  "Network": {
    "Protocol": "HTTP"
  }
}

How can I use jq to read updates.json and apply its content to content.json?

CAVEAT: I cannot predict the what's in updates.json. The jq script must be smart enough to just apply whatever it finds.

The output should be:

{
  "Type": {
    "OS": "Windows"
  },
  "Network": {
     "Protocol": "HTTP",
     "Port": 80
  }
}

This script does almost what I want:

jq 'add' -s content.json updates.json

The results are:

{
  "Type": {
    "OS": "Windows"
  },
  "Network": {
    "Protocol": "HTTP"
  }
}

But as you can see, the "Port" entry is deleted.



Solution 1:[1]

The following illustrates one approach you could take:

< content.json jq --argfile updates updates.json '
    .Network += $updates.Network
'

Or, depending on your precise requirements, you might like to consider:

< content.json jq --argfile updates updates.json '
  .Network |= with_entries(select(.value != "unknown"))
  | .Network += $updates.Network
'

Solution 2:[2]

If you want the occurrences of "unknown" to determine the updates:

< content.json jq --argfile updates updates.json '
  reduce paths(. == "unknown") as $p (.;
    setpath($p; $updates | getpath($p)) )
'

Solution 3:[3]

A more generic method:

jq -s 'def multiply:reduce .[] as $i ({}; . * $i);
       multiply' content.json updates.json

So you can put multiple files.

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 peak
Solution 2 peak
Solution 3 Philippe