0

I want to merge JSON Object to master JSON Object at required depth

Master JSON

{
  "data":{
    "barrel":{
      "length":100,
      "stage":[0,1,2]
    },
    "a":100,
    "b":200
  }
}

New JSON Object to be added at path data.barrel

{
 "width":100
}

Required Output

{
  "data":{
    "barrel":{
      "length":100,
      "stage":[0,1,2],
       "width":100
    },
    "a":100,
    "b":200
  }
}

Tried following code

String str = "{\"data\":{\"barrel\":{\"length\":100,\"stage\":[0,1,2]},\"a\":100,\"b\":200}}";
String newstr = "{\"width\":100}";
String path = "data.barrel";

JSONObject jonew = new JSONObject(newstr);

Josson josson = Josson.fromJsonString(str);
Josson jossonNew = Josson.fromJsonString(jonew.toString());

System.out.println(josson.getNode(path));
JsonNode jn = josson.getNode(path);
JsonNode jnNew = jossonNew.getNode();

Iterator<String> keys = jonew.keys();
while (keys.hasNext()) {
String key = keys.next();
    if (!jn.has(key))
    ((ObjectNode) jn).set(key, jnNew.get(key));
}

Output

{"length":100,"stage":[0,1,2],"width":100}

I am able to add child as a separate object, but not to the parent JSON Object I need a generic way as the path and depth can be varying

Regards, Pranav

Pranav
  • 103
  • 7

2 Answers2

0
public void mergeJSON(JsonObject masterJson, String path, JsonObject newJson) 
{
    String[] keys = path.split("\\.");

    JsonObject currentJson = masterJson;
    for (int i = 0; i < keys.length - 1; i++) {
      String key = keys[i];
      if (currentJson.has(key) && currentJson.get(key).isJsonObject()) {
        currentJson = currentJson.getAsJsonObject(key);
      } else {
        JsonObject nestedJson = new JsonObject();
        currentJson.add(key, nestedJson);
        currentJson = nestedJson;
      }
    }

    String lastKey = keys[keys.length - 1];
    currentJson.add(lastKey, newJson);
  }

and then you can invoke this method

mergeJSON(masterJson, "data.barrel", newJson);
String updatedJsonString = gson.toJson(masterJson);
System.out.println(updatedJsonString);
Sashika
  • 21
  • 1
  • Hello @Sashika. the output is "{\"data\":{\"barrel\":{\"width\":100},\"a\":100,\"b\":200}}". The code replace the JSON Object completely with the new JSON Object. Please refer **Required Output** above – Pranav Jun 23 '23 at 11:10
  • No this `System.out.println(updatedJsonString) => {"data":{"barrel":{"width":100},"a":100,"b":200}}` but if you want to make it pretty you can use something like, `mergeJSON(masterJson, "data.barrel", newJson); System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(masterJson));` – Sashika Jun 23 '23 at 11:29
  • I am not pointing out on format. the **barrel** object should have 3 keys. **length and stage** from master and **width** from newly added. {"data":{"barrel":{"length":100,"stage":[0,1,2],"width":100},"a":100,"b":200}} – Pranav Jun 23 '23 at 11:46
0

Deserialization

Josson master = Josson.fromJsonString(
    "{" +
    "  \"data\":{" +
    "    \"barrel\":{" +
    "      \"length\":100," +
    "      \"stage\":[0,1,2]" +
    "    }," +
    "    \"a\":100," +
    "    \"b\":200" +
    "  }" +
    "}");

By Parameters

Map<String, JsonNode> params = new HashMap<>();
params.put("$new", Josson.readJsonNode("{\"width\":100}"));
JsonNode node = master.getNode(
    "field(data.field(barrel.mergeObjects(?, $new)))", params);
System.out.println(node.toPrettyString());

By Inline

String addNew = "{\"width\":100}"; // any ' needs to double it ''
JsonNode node = master.getNode(
    "field(data.field(barrel.mergeObjects(?, json('" + addNew + "'))))");
System.out.println(node.toPrettyString());

Output

{
  "data" : {
    "barrel" : {
      "length" : 100,
      "stage" : [ 0, 1, 2 ],
      "width" : 100
    },
    "a" : 100,
    "b" : 200
  }
}
Raymond Choi
  • 1,065
  • 2
  • 7
  • 8
  • Hello Raymond, above code works good for the said path **"data.barrel"**. But I need some generic way where the path can be anything and upto any depth say eg: **data.pump** or **data.pump.specification** – Pranav Jun 23 '23 at 10:45
  • _Josson_ function `field()` can add/update/remove object elements and function `mergeObjects()` can merge two or more objects into one. For nested object with level N, use syntax `field(level1.field(level2....field(levelN.mergeObjects(?, $new))...))` for your case. – Raymond Choi Jun 23 '23 at 13:45