skip to Main Content

I need to update a JSONObject only having the part of json which has been updated and not the complete json. How can I update it without losing all the other fields? I’m looking for a generalized function that works with all types of JSONObjects.

Here’s an example:

Original JSON:

{
        "title": "Lamp",
        "events": {
            "overheating": {
                "data": {
                    "type": "string"
                },
                "forms": [
                    {
                        "href": "https://www.lamp.com/oh",
                        "subprotocol": "longpoll"
                    }
                ]
            }
        },
        "actions": {
            "toggle": {
                "forms": [
                    {
                        "href": "https://lampione.it/toggle"
                    }
                ]
            }
        },
        "@context": "https://www.w3.org/2019/wot/td/v1",
        "security": [
            "basic_sc"
        ],
        "properties": {},
        "securityDefinitions": {
            "basic_sc": {
                "in": "header",
                "scheme": "basic"
            }
        },
        "id": "urn:uuid:8c426e18-f579-42b1-a3c9-7aa9c86fbacf"
    }

Update input:

{"events":{"overheating":{"forms":[{"href":"https://lampada.it/oh","subprotocol":"longpoll"}]}}}

In this case the only thing that changes is the "href" field but if I replaced events field I would lose the "data" field.

Thanks in advance.

2

Answers


  1. Chosen as BEST ANSWER

    Here is my solution in Java, using the suggestions i got from @Mel Habip and @Rogue. Before using it, test it since some errors may not be handled in the way you want. It is a recursive function that stops when one of the given inputs is not a JSONObject (that means it has reached the most "nested" field).

    public static Object specialMerger(Object original, Object change) throws JSONException {
        if (original == null) {
            return change;
        }
    
        if (original instanceof JSONObject && change instanceof JSONObject) {
            JSONObject originalObj = (JSONObject) original;
            JSONObject changeObj = (JSONObject) change;
            JSONObject merged = new JSONObject(originalObj.toString());
    
            Iterator<String> keys = changeObj.keys();
    
            while (keys.hasNext()) {
                String key = keys.next();
                if (originalObj.has(key)) {
                    merged.put(key, specialMerger(originalObj.get(key), changeObj.get(key)));
                } else {
                    merged.put(key, changeObj.get(key));
                }
            }
            return merged;
        } else {
            return change;
        }
    }
    

  2. Consider the following function:

    function specialMerger(original, change) {
        if (typeof original !== 'object' || typeof change !== 'object') {
          return change; // If either is not an object, return the change value.
        }
      
        const merged = { ...original };
      
        for (const key in change) {
          if (change.hasOwnProperty(key)) {
            if (original.hasOwnProperty(key)) {
              // If the key exists in both objects, recursively merge them.
              merged[key] = specialMerger(original[key], change[key]);
            } else {
              // If the key doesn't exist in the original object, add it.
              merged[key] = change[key];
            }
          }
        }
      
        return merged;
      }
    

    We use the for ... in loop to iterate over the keys in a hash or the indexes in an array. This relies of the pass-by-reference property of objects.

    We also use recursion to go as "deep" as we need to, where we recurse if the level we’re at is still an object/array.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search