Skip to content

Examples

Oswaldo Baptista Vicente Junior edited this page Jul 18, 2024 · 11 revisions

Merge JSON documents with a distinct key on an array

ℹ️ Note: This example uses json-smart as JSON provider, but the logic is provider-agnostic.

Suppose you have the following JSON objects previously loaded:

  • JSONObject json1

    {
      "agents": [
        {
          "class": "Agent1",
          "interval": "1 minute"
        },
        {
          "class": "Agent2",
          "interval": "2 minutes"
        }
      ]
    }
  • JSONObject json2

    {
      "agents": [
        {
          "class": "Agent2",
          "interval": "2 hours"
        },
        {
          "class": "Agent3",
          "interval": "3 minutes"
        }
      ]
    }
  1. Create a JsonMerger of type net.minidev.json.JSONObject:
import net.minidev.json.JSONObject;
import net.obvj.jsonmerge.*;
...
JsonMerger<JSONObject> merger = new JsonMerger<>(JSONObject.class);
  1. Merge both objects, defining a distinct key class to identify each object inside the $.agents list:
JSONObject merged = merger.merge(json1, json2,
        JsonMergeOption.onPath("$.agents").findObjectsIdentifiedBy("class")
                       .thenPickTheHighestPrecedenceOne());
---
config:
  sankey:
    showValues: false
    width: 680
    height: 180
    linkColor: 'source'
---
sankey-beta

json1,agents[?(@.class=='Agent1')],.5
json1,agents[?(@.class=='Agent2')],.25

agents[?(@.class=='Agent1')],result,.5
agents[?(@.class=='Agent2')],result,.25

json2,agents[?(@.class=='Agent2')],.25
json2,agents[?(@.class=='Agent3')],.5

agents[?(@.class=='Agent2')],result,.25
agents[?(@.class=='Agent3')],result,.5

Loading

💡 The JSON generated by the merge operation will be as follows:

{
  "agents": [
    {
      "class": "Agent1",
      "interval": "1 minute"
    },
    {
      "class": "Agent2",
      "interval": "2 minutes"
    },
    {
      "class": "Agent3",
      "interval": "3 minutes"
    }
  ]
}
🔝 Back to top

Merge JSON documents with two distinct keys on an array

ℹ️ Note: This example uses json-smart as JSON provider, but the logic is provider-agnostic.

Suppose you have the following JSON objects previously loaded:

  • JSONObject drive1

    {
      "files": [
        {
          "name": "file1.txt",
          "version": "1",
          "date": "2022-07-07T10:42:21"
        },
        {
          "name": "file1.txt",
          "version": "2",
          "date": "2022-08-06T09:40:01"
        },
        {
          "name": "file2.txt",
          "version": "1",
          "date": "2022-08-06T09:51:40"
        }
      ]
    }
  • JSONObject drive2

    {
      "files": [
        {
          "name": "file1.txt",
          "version": "1",
          "date": "2022-07-07T10:42:21"
        },
        {
          "name": "file1.txt",
          "version": "2",
          "date": "2022-08-06T09:40:01"
        },
        {
          "name": "file3.txt",
          "version": "1",
          "date": "2022-08-18T17:31:22"
        }
      ]
    }
  1. Create a JsonMerger of type net.minidev.json.JSONObject:
import net.minidev.json.JSONObject;
import net.obvj.jsonmerge.*;
...
JsonMerger<JSONObject> merger = new JsonMerger<>(JSONObject.class);
  1. Merge both objects, defining two keys name and version to identify each object inside the $.files list:
JSONObject merged = merger.merge(drive1, drive2,
        JsonMergeOption.onPath("$.files").findObjectsIdentifiedBy("name", "version")
                       .thenPickTheHighestPrecedenceOne());
---
config:
  sankey:
    showValues: false
    width: 770
    height: 240
    linkColor: 'source'
---
sankey-beta

drive1,$.files[?(@.name=='file1.txt' && @.version=='1')],.25
drive1,$.files[?(@.name=='file1.txt' && @.version=='2')],.25
drive1,$.files[?(@.name=='file2.txt' && @.version=='1')],.5

$.files[?(@.name=='file1.txt' && @.version=='1')],result,.5
$.files[?(@.name=='file1.txt' && @.version=='2')],result,.5
$.files[?(@.name=='file2.txt' && @.version=='1')],result,.5

drive2,$.files[?(@.name=='file1.txt' && @.version=='1')],.25
drive2,$.files[?(@.name=='file1.txt' && @.version=='2')],.25
drive2,$.files[?(@.name=='file3.txt' && @.version=='1')],.5

$.files[?(@.name=='file3.txt' && @.version=='1')],result,.5
Loading

💡 The JSON generated by the merge operation will be as follows:

   {
     "files": [
       {
         "name": "file1.txt",
         "version": "1",
         "date": "2022-07-07T10:42:21"
       },
       {
         "name": "file1.txt",
         "version": "2",
         "date": "2022-08-06T09:40:01"
       },
       {
         "name": "file2.txt",
         "version": "1",
         "date": "2022-08-06T09:51:40"
       },
       {
         "name": "file3.txt",
         "version": "1",
         "date": "2022-08-18T17:31:22"
       }
     ]
   }
🔝 Back to top

Deep merge complex JSON documents

ℹ️ Note: This example uses json-smart as JSON provider, but the logic is provider-agnostic.

Suppose you have the following JSON objects previously loaded:

  • JSONObject users1

    {
      "sites": [
        {
          "id": "latinamerica-1",
          "users": [
            {
              "name": "Camille Lawson",
              "email": "camillelawson@zolarex.com.br",
              "friends": [],
              "preferences": [
                {
                  "key": "language", 
                  "value": "pt-BR"
                },
                {
                  "key": "theme",
                  "value": "light high contrast"
                }
              ]
            },
            {
              "name": "Johnnie Alvarado",
              "email": "johnniealvarado@accupharm.com.co",
              "friends": ["Morrow Rasmussen", "Bertie Skinner"],
              "preferences": [
                {
                  "key": "timeZone",
                  "value": "COT"
                },
                {
                  "key": "theme",
                  "value": "light"
                }
              ]
            }
          ]
        }
      ]
    }
  • JSONObject users2

    {
      "sites": [
        {
          "id": "latinamerica-1",
          "users": [
            {
              "name": "Camille Lawson",
              "email": "camillelawson@zolarex.com.br",
              "friends": ["Johnnie Alvarado"],
              "preferences": [
                {
                  "key": "theme",
                  "value": "dark"
                }
              ]
            },
            {
              "name": "Morrow Rasmussen",
              "email": "morrowrasmussen@dogspa.com.cl",
              "friends": ["Johnnie Alvarado", "Nikki Hamilton"],
              "preferences": []
            },
            {
              "name": "Johnnie Alvarado",
              "email": "johnniealvarado@accupharm.com.co",
              "friends": ["Bertie Skinner"],
              "preferences": [
                {
                  "key": "language",
                  "value": "es-CO"
                }
              ]
            }
          ]
        }
      ]
    }
  1. Create a JsonMerger of type net.minidev.json.JSONObject:
import net.minidev.json.JSONObject;
import net.obvj.jsonmerge.JsonMerger;
...
JsonMerger<JSONObject> merger = new JsonMerger<>(JSONObject.class);
  1. Merge both objects, defining custom merge options for each list in the document tree:

💡 Hint: Add a static import of net.obvj.jsonmerge.JsonMergeOption.* for better readability:

JSONObject result = merger.merge(users1, users2,
        onPath("$.sites").findObjectsIdentifiedBy("id").thenDoADeepMerge(),
        onPath("$.sites[*].users").findObjectsIdentifiedBy("name", "email").thenDoADeepMerge(),
        onPath("$.sites[*].users[*].friends").addDistinctObjectsOnly(),
        onPath("$.sites[*].users[*].preferences").findObjectsIdentifiedBy("key")
                    .thenPickTheHighestPrecedenceOne());

💡 The JSON generated by the merge operation will be as follows:

   {
     "sites": [
       {
         "id": "latinamerica-1",
         "users": [
           {
             "name": "Camille Lawson",
             "email": "camillelawson@zolarex.com.br",
             "friends": ["Johnnie Alvarado"],
             "preferences": [
               {
                 "key": "language", 
                 "value": "pt-BR"
               },
               {
                 "key": "theme",
                 "value": "light high contrast"
               }
             ]
           },
           {
             "name": "Morrow Rasmussen",
             "email": "morrowrasmussen@dogspa.com.cl",
             "friends": ["Johnnie Alvarado", "Nikki Hamilton"],
             "preferences": []
           },
           {
             "name": "Johnnie Alvarado",
             "email": "johnniealvarado@accupharm.com.co",
             "friends": ["Morrow Rasmussen", "Bertie Skinner"],
             "preferences": [
               {
                 "key": "timeZone",
                 "value": "COT"
               },
               {
                 "key": "theme",
                 "value": "light"
               },
               {
                 "key": "language",
                 "value": "es-CO"
               }
             ]
           }
         ]
       }
     ]
   }
🔝 Back to top