3

Modifying the question to be more specific. There will be 2 JSON files where first one will have few blocks. And second one will have few blocks with few addition of redirection rules as you can see

"values": [
  "/businessclass/articles/money.page",
  "/businessclass/articles/1.page",
  "/businessclass/articles/2.page"
],

Output should be merge of 2 files. Including json File 1 changes and Json 2 updated redirect rules.

JSON file 1

[
  {
    "name": "caching",
    "options": {
      "behavior": "MAX_AGE",
      "mustRevalidate": false,
      "ttl": "10m",
      "defaultTtl": "30m"
    }
  },
  {
    "name": "/businessclass/articles/money.page",
    "children": [],
    "behaviors": [
      {
        "name": "redirect",
        "options": {
          "destinationPathOther": "/businessclass/articles/finance-and-operations.page"
        }
      }
    ],
    "criteria": [
      {
        "name": "path",
        "options": {
          "matchOperator": "MATCHES_ONE_OF",
          "values": [
            "/businessclass/articles/money.page"
          ],
          "matchCaseSensitive": false
        }
      }
    ],
    "criteriaMustSatisfy": "all",
    "comments": ""
  }
]

JSON file 2

{
  "name": "/businessclass/articles/money.page",
  "children": [],
  "behaviors": [
    {
      "name": "redirect",
      "options": {
        "destinationPathOther": "/businessclass/articles/finance-and-operations.page"
      }
    }
  ],
  "criteria": [
    {
      "name": "path",
      "options": {
        "matchOperator": "MATCHES_ONE_OF",
        "values": [
          "/businessclass/articles/money.page",
          "/businessclass/articles/1.page",
          "/businessclass/articles/2.page"
        ],
        "matchCaseSensitive": false
      }
    }
  ],
  "criteriaMustSatisfy": "all",
  "comments": ""
}

Expected output

[
  {
    "name": "caching",
    "options": {
      "behavior": "MAX_AGE",
      "mustRevalidate": false,
      "ttl": "10m",
      "defaultTtl": "30m"
    }
  },
  {
    "name": "/businessclass/articles/money.page",
    "children": [],
    "behaviors": [
      {
        "name": "redirect",
        "options": {
          "destinationPathOther": "/businessclass/articles/finance-and-operations.page"
        }
      }
    ],
    "criteria": [
      {
        "name": "path",
        "options": {
          "matchOperator": "MATCHES_ONE_OF",
          "values": [
            "/businessclass/articles/money.page",
            "/businessclass/articles/1.page",
            "/businessclass/articles/2.page"
          ],
          "matchCaseSensitive": false
        }
      }
    ],
    "criteriaMustSatisfy": "all",
    "comments": ""
  }
]

Well. The order of rules can be changed. And, sometimes new rules with new names can be added to the json file like "name": "/businessclass/articles/money.page". So whatever be the changes, have to find the delta and need to merge the files accordingly. Or can create new json file which contains merged changes also.

3 Answers 3

6

If I understand your question correctly, you just want to output an array which contains the object in each file. In this case, -s will already do that for you, so you just need

jq -s . file1 file2

If you need additional transformations, please edit the question and give a short summary what you need (I didn't compare the expected result line-by-line with the actual output).

Edit

I am still not exactly sure about the general nature of the transformation you need, but if the format is exactly as in the example, and all you want is to replace the values field in the first file with contents of the values field in the second file, and keep everything else, try

jq -s '.[0][1].criteria[0].options.values=.[1].criteria[0].options.values' file1 file2

Here -s returns the files as an array, so .[0] is the first file and .[1] the second file. It then just selects static paths, and updates a single matching field in the first place.

If the order or number of your objects is variable, or if the substituation should only happen for matching objects etc., please update the question.

2
  • Thanks for the right guidance. It was one of the requirement merging 2 json files into 1. As you have asked, I have modified the question to be more specific. Please let me know if you need any further details. Oct 21, 2018 at 8:49
  • Thanks for the prompt response. Yes. the structure of the json can be changed and few new rules can be added also. I have updated the question with those details. Oct 21, 2018 at 9:32
4

My favorite tool for JSON and YAML merging is Spruce. The command to get JSON on output would be:

spruce merge file1.json file2.json | spruce json
1

Do a relational JOIN operation between the two files based on the .name key in the array of the first JSON file and the .name key in the second file.

For elements that happens to have the same .name value, pick the element from the second file, otherwise, pick the element from the first file.

jq -s '[ JOIN(INDEX(.[1]; .name); .[0][]; .name; .[1] // .[0]) ]' file1 file2

In a similar manner, select all entries of the array in the first file that has a .name key with the same value as in the second file. Update these entries with the data from the second file.

jq -s '[ .[1] as $u | .[0][] | select(.name == $u.name) |= $u ]' file1 file2

In both of these variations (except for at the end of the first command), .[0] is the data in the first file (an array) while .[1] is the data in the second file (a single object). Both commands generates the expected output given the input shown in the question.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .