Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gson JsonObject copy value affected others JsonObject instance

Tags:

java

gson

I have weird problem with gson (my gson version is 2.3.1) I have JsonObject instance called jsonObject (JsonObject jsonObject) jsonObject has value, not empty And I create another one, JsonObject tempOject = jsonObject; So, when I try to remove element inside tempObject, lets say, tempObject.remove("children");

Then that code affected the jsonObject instance.

Here is the code snippet :

jsonObject              = element.getAsJsonObject();
        JsonElement tempElement = element;
        JsonObject tempObject   = jsonObject;
        String tempJson;

        if(tempObject.has("children")){
            tempObject.remove("children");
            tempJson = tempObject.toString();
            tempElement = new JsonParser().parse(tempJson);
        }

        if(nodes.isEmpty()){
            elements = new ArrayList<>();
            nodes.put(iterator, elements);
        }
        if(!nodes.containsKey(iterator)){
            elements = new ArrayList<>();
            nodes.put(iterator, elements);
        }
        nodes.get(iterator).add(tempElement);

        if (jsonObject.has("children")){
            tempNextJson        = jsonObject.get("children").toString();
            tempCurrJson        = jsonObject.toString();

            tempIterator++;
            metaDataProcessor(tempNextJson, tempCurrJson, tempNextJson, tempIterator, maxLevel);
        }

I have read the gson JsonObject class, it use deep copy method. That was not supposed to affected the reference since JsonObject using deep value copy, so the returned JsonObject object is the new one.

But why this is happened?

Anyway...there is deepCopy method inside JsonObject class

JsonObject deepCopy() {
    JsonObject result = new JsonObject();
    Iterator i$ = this.members.entrySet().iterator();

    while(i$.hasNext()) {
        Entry entry = (Entry)i$.next();
        result.add((String)entry.getKey(), ((JsonElement)entry.getValue()).deepCopy());
    }

    return result;
}

But thats an abstract method from JsonElement class which implemented on JsonObject, and the attribute not set as public, so I cannot call that method. But I guess that method supposedly called directly when I do instance copy.

How about that?

Thanks in advance

like image 1000
otnieldocs Avatar asked Apr 22 '15 01:04

otnieldocs


2 Answers

This can be used to copy any object of any type! just have to use Gson.

public <T> T deepCopy(T object, Class<T> type) {
    try {
        Gson gson = new Gson();
        return gson.fromJson(gson.toJson(object, type), type);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

in your case you can call it like:

JsonObject jsonObject = deepCopy(oldJsonObject, JsonObject.class);
like image 200
Muhammad Alfaifi Avatar answered Sep 27 '22 02:09

Muhammad Alfaifi


Starting from version 2.8.2, deepCopy() in Gson JsonElement is public, so you can now use it to make a deep copy of your JSON object.

like image 34
JaakkoK Avatar answered Sep 27 '22 02:09

JaakkoK