Home > Back-end >  Merging two json files with jq
Merging two json files with jq

Time:08-15

I have the following json files:

File1:

[
    {
      "id": 1,
      "name": "serviceName",
      "owner": {
        "id": 1,
        "name": "Nicole"
      }
    }
]

and File2:

[
    {
      "id": 1,
      "name": "Nicole",
      "email": "[email protected]"
    }
]

I would like to have them merged like this:

[
    {
      "id": 1,
      "name": "serviceName",
      "owner": {
        "id": 1,
        "name": "Nicole",
        "email": "[email protected]"
      }
    }
]

I'm trying the approach from here and try to use the following:

jq --argfile new file2.json '
 ($new | INDEX(.ID)) as $dict
 | .owner
     |= (if $dict[.ID] then .   $dict[.ID] else . end)
' file1.json

But that just results in an error.

Can anyone maybe provide me with some tips?

CodePudding user response:

Your approach fails because of the followings:

  • Field names are case-sensitive. Having {"id": 1}, use .id, not .ID.
  • Field names are strings. Having {"id": 1} and INDEX(.id) as $dict, use $dict[.id | tostring] or $dict[.id | @text] or $dict["\(.id)"] to convert the number 1 into the string "1" in the object index.
  • Your files contain arrays. While INDEX defaults to read .[] from file2.json, you need to do it for file1.json yourself.
jq --argfile new file2.json '
  ($new | INDEX(.id)) as $dict | .[].owner |= (
    if $dict[.id | @text] then .   $dict[.id | @text] else . end
  )
' file1.json
[
  {
    "id": 1,
    "name": "serviceName",
    "owner": {
      "id": 1,
      "name": "Nicole",
      "email": "[email protected]"
    }
  }
]

As a suggestion, you could also employ JOIN to merge on a given key:

jq '
  JOIN(
    INDEX(input[]; .id); .[]; .id | @text; .[0].owner  = .[1] | .[0]
  )
' file1.json file2.json
[
  {
    "id": 1,
    "name": "serviceName",
    "owner": {
      "id": 1,
      "name": "Nicole",
      "email": "[email protected]"
    }
  }
]

Demo

  • Related