skip to Main Content

With jq command, I want to merge multiple json files.

But I have no idea how to achieve below expectation.

thanks in advance

a.json

{
    "key1": {
        "key2": [
            1,
            2
        ]
    },
    "key3": "aaa"
}

b.json

{
    "key1": {
        "key2": [
            3,
            4,
            5
        ]
    },
    "key4": "bbb"
}

expected result

{
    "key1": {
        "key2": [
            1,
            2,
            3,
            4,
            5
        ]
    },
    "key3": "aaa",
    "key4": "bbb"
}

2

Answers


  1. jq -s 'reduce .[] as $item ({}; . + ($item | with_entries(if .key == "key1" then .value = (.value + $item.key1) else . end)))' a.json b.json

    Login or Signup to reply.
  2. The problem is, that you want to merge like * would, but treat colliding arrays like + would. You could prepare those arrays such that merging with * will eventually work as desired, e.g. by pre-processing the addition, and storing it in the last affected array.

    # Use with option `jq -s` so that the inputs are collected into an array
    reduce (
      # Find highest ranked arrays
      [paths(arrays) | select(all(.[1:][]; type == "string"))]
      # Group those that would collide
      | group_by(.[1:])[]
    ) as $group (.;
      # Store the addition into the last of those arrays
      setpath($group[-1]; [getpath($group[])] | add)
    )
    # Perform the actual merge (for only two inputs, `first * last` would suffice)
    | reduce .[1:][] as $next (first; . * $next)
    
    {
      "key1": {
        "key2": [
          1,
          2,
          3,
          4,
          5
        ]
      },
      "key3": "aaa",
      "key4": "bbb"
    }
    

    Demo


    Alternatively, use another JSON processor that provides such merging techniques. For example, mikefarah/yq implements a *+ operator that "merges objects, but appends arrays". Note that yq is primarily a YAML processor (so the manual is focused around YAML examples) but it can also handle JSON input/output (if not clear from the filename extensions, use the explicit -pj -oj flags).

    yq '. *+ load("b.json")' a.json
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search