1

I've got 2 json files and want to merge them into one file. Here the content of files:

a.json:

{
    "config":
    {
        "config1":
        {
            "config11":
            {
                "apple":"apple",
                "orange":"orange",
                "lemon":[
                    "lemon1",
                    "lemon2",
                    "lemon3"
                ],
                "pear":"pear"
            }
        },
        "config2":
        {
            "config21":"hello",
            "config22":"goodbye"
        }
    }
}

b.json:

{
    "config":
    {
        "config1":
        {
            "config11":
            {
                "apple":null,
                "orange":null,
                "lemon":[
                    "lemon4",
                    "lemon5",
                    "lemon6"
                ],
                "pear":null
            }
        },
        "config2":
        {
            "config21":"hey",
            "config22":null
        }
    }
}

I want to merge the not-null part of b.json into a.json

Expected result:

{
    "config":
    {
        "config1":
        {
            "config11":
            {
                "apple":"apple",
                "orange":"orange",
                "lemon":[
                    "lemon4",
                    "lemon5",
                    "lemon6"
                ],
                "pear":"pear"
            }
        },
        "config2":
        {
            "config21":"hey",
            "config22":"goodbye"
        }
    }
}

I try this command:

jq -s '.[0] + .[1]' a.json b.json

but the output is not i want

i read https://stedolan.github.io/jq/manual ,but i still don't know how to do

Any helps?Thank you.

append:

aa.json

{
  "config": {
    "config_again": {
      "country": {
        "countrylist": [
          "CANADA",
          "MEXICO",
          "USA"
        ]
      },
      "language": {
        "languageorderlist": [
          "en_US",
          "hu_HU",
          "in_ID",
          "it_IT",
          "iw_IL",
          "zh_CN"
        ]
      },
      "video": {
        "mp4": "1",
        "mkv": "1"
      },
      "Audio": {
        "audio_audio": "0x111111"
      }
    }
  }
}

bb.json:

{
  "config": {
    "config_again": {
      "country": {
        "countrylist": [
          "USA"
        ]
      },
      "language": {
        "languageorderlist": [
          "en_US",
          "de_DE"
        ]
      },
      "video": {
        "mp4": null,
        "mkv": null
      },
      "Audio": {
        "audio_audio": "0x666666"
      }
    }
  }
}
newbie
  • 31
  • 5

2 Answers2

3

The key to a simple solution here is using paths, getpath, and setpath, e.g. like so:

Invocation

jq -f program.jq --argfile b b.json a.json

program.jq

reduce ($b | paths(scalars)) as $p (.;
  ($b|getpath($p)) as $v
  | if $v != null then setpath($p; $v) else . end)
peak
  • 105,803
  • 17
  • 152
  • 177
  • You've spent more time looking at it than I have -- is this actually a distinct, non-duplicative question? (At a glance I'm not seeing the distinguishing factors). – Charles Duffy Feb 03 '21 at 19:54
  • Good question, but I was not optimistic that I could find it without wasting quite a lot of time .... – peak Feb 03 '21 at 20:03
  • Hmm. Looking a little closer, I'd argue that it could be close with _two_ duplicates, [remove all null values](https://stackoverflow.com/questions/39500608/remove-all-null-values) and [How to merge 2 json objects from 2 files using jq](https://stackoverflow.com/questions/19529688/how-to-merge-2-json-objects-from-2-files-using-jq), but while combining the two answers would work, the end result would not be as clean as what you're doing here, so there's value to keeping it open. – Charles Duffy Feb 03 '21 at 20:19
  • Thanks. but in this case( i add another two json files aa.json and bb.json), `jq -f program.jq --argfile b bb.json aa.json`, it doesn't work. I can't figure out the reason. i found another way:[Merging JSON files recursively in the command-line](https://e.printstacktrace.blog/merging-json-files-recursively-in-the-command-line/) – newbie Feb 04 '21 at 07:00
1

Merging JSON files recursively in the command-line

deepmerge.jq:

def deepmerge(a;b):                                                                                                                                                  
    reduce b[] as $item (a; 
        reduce ($item | keys_unsorted[]) as $key (.; 
            $item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "object") then
            deepmerge({}; [if .[$key] == null then {} else .[$key] end, $val])
            elif ($type == "null") then
            .[$key]
            else
            $val
            end)
        );   
    deepmerge({}; .)
jq -f deepmerge.jq -s aa.json bb.json

it works

newbie
  • 31
  • 5