Gson JsonObject 复制值影响其他 JsonObject 实例
Gson JsonObject copy value affected others JsonObject instance
我的 gson 有奇怪的问题(我的 gson 版本是 2.3.1)
我有一个名为 jsonObject (JsonObject jsonObject) 的 JsonObject 实例
jsonObject 有值,不为空
我创建了另一个 JsonObject tempOject = jsonObject;
所以,当我尝试删除 tempObject 中的元素时,可以说,
tempObject.remove("children");
然后该代码影响了 jsonObject 实例。
这是代码片段:
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);
}
我读过gson JsonObject class,它使用深拷贝方法。这不应该影响引用,因为 JsonObject 使用深度值复制,所以返回的 JsonObject 对象是新对象。
但为什么会这样呢?
反正...JsonObject里面有deepCopy方法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;
}
但那是 JsonElement class 的一个抽象方法,它在 JsonObject 上实现,并且属性未设置为 public,所以我无法调用该方法。但是我猜那个方法据说是在我做实例复制的时候直接调用的。
怎么样?
提前致谢
设置tempObject = jsonObject
不会为您创建第二个对象。所做的只是创建另一个对原始 jsonObject.
的引用
你想要做的是:
JSONObject tempObject = new JSONObject(jsonObject.toString());
tempObject.remove("children");
这将创建一个 new JsonObject,它是您拥有的原始 json 的副本。
如果只能使用 GSON 库,可以使用 JsonObject.deepyCopy() 方法。在 r855 中添加:https://code.google.com/p/google-gson/source/detail?r=855
使用 deepCopy() 方法会是
JsonObject tempObject = jsonObject.deepCopy();
tempObject.remove("children");
我找到了最简单的解决方案。由于 JsonObject 的 deepCopy() 方法似乎不起作用,所以我只是将 JsonObject 值转换为字符串,然后使用 JsonParser() 转换为 JsonElement。
然后从我们的新 JsonObject 中创建一些新的 JsonObject。它看起来更简单,而不是创建一些需要重新实现 deepCopy 的辅助方法。如果我们重新实现迭代,必须考虑 JsonObject 的深度。由于JsonObject是hashmap(LinkedTreeMap),value是JsonElement,所以需要通过JsonElement递归解析。
这可以用来复制任何类型的任何对象!
只需要使用 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;
}
}
在你的情况下,你可以这样称呼它:
JsonObject jsonObject = deepCopy(oldJsonObject, JsonObject.class);
看起来 Gson 开发人员决定不公开 deepCopy()
。您可以将 JsonElement
序列化为字符串并返回,但是,我认为在 JsonObject
之外实施深度克隆效率更高。这是我的解决方案:
@Nonnull
public static JsonObject deepCopy(@Nonnull JsonObject jsonObject) {
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
result.add(entry.getKey(), deepCopy(entry.getValue()));
}
return result;
}
@Nonnull
public static JsonArray deepCopy(@Nonnull JsonArray jsonArray) {
JsonArray result = new JsonArray();
for (JsonElement e : jsonArray) {
result.add(deepCopy(e));
}
return result;
}
@Nonnull
public static JsonElement deepCopy(@Nonnull JsonElement jsonElement) {
if (jsonElement.isJsonPrimitive() || jsonElement.isJsonNull()) {
return jsonElement; // these are immutables anyway
} else if (jsonElement.isJsonObject()) {
return deepCopy(jsonElement.getAsJsonObject());
} else if (jsonElement.isJsonArray()) {
return deepCopy(jsonElement.getAsJsonArray());
} else {
throw new UnsupportedOperationException("Unsupported element: " + jsonElement);
}
}
从版本 2.8.2 开始,Gson JsonElement
中的 deepCopy()
为 public,因此您现在可以使用它来深拷贝 JSON 对象.
我的 gson 有奇怪的问题(我的 gson 版本是 2.3.1) 我有一个名为 jsonObject (JsonObject jsonObject) 的 JsonObject 实例 jsonObject 有值,不为空 我创建了另一个 JsonObject tempOject = jsonObject; 所以,当我尝试删除 tempObject 中的元素时,可以说, tempObject.remove("children");
然后该代码影响了 jsonObject 实例。
这是代码片段:
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);
}
我读过gson JsonObject class,它使用深拷贝方法。这不应该影响引用,因为 JsonObject 使用深度值复制,所以返回的 JsonObject 对象是新对象。
但为什么会这样呢?
反正...JsonObject里面有deepCopy方法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;
}
但那是 JsonElement class 的一个抽象方法,它在 JsonObject 上实现,并且属性未设置为 public,所以我无法调用该方法。但是我猜那个方法据说是在我做实例复制的时候直接调用的。
怎么样?
提前致谢
设置tempObject = jsonObject
不会为您创建第二个对象。所做的只是创建另一个对原始 jsonObject.
你想要做的是:
JSONObject tempObject = new JSONObject(jsonObject.toString());
tempObject.remove("children");
这将创建一个 new JsonObject,它是您拥有的原始 json 的副本。
如果只能使用 GSON 库,可以使用 JsonObject.deepyCopy() 方法。在 r855 中添加:https://code.google.com/p/google-gson/source/detail?r=855
使用 deepCopy() 方法会是
JsonObject tempObject = jsonObject.deepCopy();
tempObject.remove("children");
我找到了最简单的解决方案。由于 JsonObject 的 deepCopy() 方法似乎不起作用,所以我只是将 JsonObject 值转换为字符串,然后使用 JsonParser() 转换为 JsonElement。 然后从我们的新 JsonObject 中创建一些新的 JsonObject。它看起来更简单,而不是创建一些需要重新实现 deepCopy 的辅助方法。如果我们重新实现迭代,必须考虑 JsonObject 的深度。由于JsonObject是hashmap(LinkedTreeMap),value是JsonElement,所以需要通过JsonElement递归解析。
这可以用来复制任何类型的任何对象! 只需要使用 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;
}
}
在你的情况下,你可以这样称呼它:
JsonObject jsonObject = deepCopy(oldJsonObject, JsonObject.class);
看起来 Gson 开发人员决定不公开 deepCopy()
。您可以将 JsonElement
序列化为字符串并返回,但是,我认为在 JsonObject
之外实施深度克隆效率更高。这是我的解决方案:
@Nonnull
public static JsonObject deepCopy(@Nonnull JsonObject jsonObject) {
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
result.add(entry.getKey(), deepCopy(entry.getValue()));
}
return result;
}
@Nonnull
public static JsonArray deepCopy(@Nonnull JsonArray jsonArray) {
JsonArray result = new JsonArray();
for (JsonElement e : jsonArray) {
result.add(deepCopy(e));
}
return result;
}
@Nonnull
public static JsonElement deepCopy(@Nonnull JsonElement jsonElement) {
if (jsonElement.isJsonPrimitive() || jsonElement.isJsonNull()) {
return jsonElement; // these are immutables anyway
} else if (jsonElement.isJsonObject()) {
return deepCopy(jsonElement.getAsJsonObject());
} else if (jsonElement.isJsonArray()) {
return deepCopy(jsonElement.getAsJsonArray());
} else {
throw new UnsupportedOperationException("Unsupported element: " + jsonElement);
}
}
从版本 2.8.2 开始,Gson JsonElement
中的 deepCopy()
为 public,因此您现在可以使用它来深拷贝 JSON 对象.