Is there a reason why the deepCopy methods are not public? I see that they were public for some time in an earlier revision then was made "default" access level but I couldn't find the reason.
It was never made public in a released version. No specific reason, we just didn't see it useful enough to bloat our API. What are you trying to do that you need it?
It was never made public in a released version.
Fair enough, I was only checking the file history and didn't notice that, sorry.
What are you trying to do that you need it?
To be exact for this but a shorter version is:
class Demo {
private JsonObject serverResponse;
public JsonObject getResultsFromResponse() {
JsonObject results = serverResponse.getAsJsonObject("results");
results.add("SOME_DEFAULT_DATA", "");
return results;
}
}
In this code piece calling getResultsFromResponse will change content of the class variable serverResponse but actually what I needed was to add the default data field only to the object returned by that method. So what I wanted to do is create a copy of results then add the default field to it and return so that serverResponse would not be affected - but this is not possible without access to deepCopy.
Let me know if I overlooked something or if this is possible to do without copying.
We could support deep copy by exposing clone() with a covariant return type
on these types. We do this in OkHttp and Retrofit to great effect (not that
I'm biased towards those libraries or anything).
On Sat, Dec 26, 2015, 12:36 PM Cihat Keser [email protected] wrote:
It was never made public in a released version.
Fair enough, I was only checking the file history and didn't notice that,
sorry.What are you trying to do that you need it?
To be exact for this
https://github.com/searchbox-io/Jest/blob/master/jest-common/src/main/java/io/searchbox/client/JestResult.java#L203
but a shorter version is:class Demo {
private JsonObject serverResponse;public JsonObject getResultsFromResponse() {
JsonObject results = serverResponse.getAsJsonObject("results");
results.add("SOME_DEFAULT_DATA", "");
return results;
}
}In this code piece calling getResultsFromResponse will change content of
the class variable serverResponse but actually what I needed was to add
the default data field only to the object returned by that method. So what
I wanted to do is create a copy of results then add the default field to
it and return so that serverResponse would not be affected - but this is
not possible without access to deepCopy.Let me know if I overlooked something or if this is possible to do without
copying.—
Reply to this email directly or view it on GitHub
https://github.com/google/gson/issues/760#issuecomment-167347520.
Two things:
clone() return a shallow copy. So we’d probably want to name the method deepCopy(), and possibly also have clone() that does a shallow copy. (Reason being, the default Object.clone() is a shallow copy).JsonPrimitive by creating it with an AtomicInteger. If we expose a mechanism to deep copy, we should probably convert numbers to LazilyParsedNumber instances.And for what it’s worth, a shallow copy is sufficient to satisfy @kramer’s request.
And for what it’s worth, a shallow copy is sufficient to satisfy @kramer’s request.
@swankjesse May be true for the exact code I posted but are you sure that a shallow copy is still sufficient if the modification (the field addition) was in a deeper level (e.g.: results.getAsJsonObject("failed").add(...) - here the failed object will still be shared between the class var and the returned copy if I'm not mistaken) ?
Yep, in that case you’ll need a deep copy.
I came across this thread when I encountered the fact that I cannot extend JsonElement because of the default access level of the deepCopy. Is there any alternative for me? I want to implement my own class which extends JsonElement.
Hi @kramer, so far have you found any solution to solve the issue? I'm right facing the same issue as you did..
Hi,
I'm looking at ways to merge Jsons the way its available in lodash.
I couldn't find it with Gson. Is it available?
If not, I'm planning to write one. DeepCopy would be helpful here.
Can this is be made public?
Regards,
No specific reason to hide deepCopy (except to have a smaller API set).
For now, you can copy over the code?
@inder123 now i did the deepCopy in this way for Gson
`/**
* This method makes a "deep copy" of JsonElement it is given.
*/
public static JsonElement deepClone(JsonElement element) {
try {
String elementString = element.toString();
return new JsonParser().parse(elementString);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}`
So far it works for what I need, but I'm not sure whether it is good in term of process performance.
+1 for making deepCopy() public. My code below would alter the source, which I'd like to prevent:
private JsonElement removeAttribute(String attribute, JsonObject source) {
source.remove(attribute);
return source;
}
+1 deepCopy() should be public, I would use it when merging two JsonObject's into one when the JsonObjects are settings and default settings... like so...
public static JsonObject merge(String overrideJson, JsonObject defaultObj) {
return mergeInto((JsonObject)new JsonParser().parse(overrideJson), defaultObj);
}
public static JsonObject merge(JsonObject overrideObj, JsonObject defaultObj) {
return mergeOverride((JsonObject)deepClone(defaultObj), overrideObj);
}
public static JsonObject mergeOverride(JsonObject targetObj, JsonObject overrideObj) {
for (Map.Entry<String, JsonElement> entry : overrideObj.entrySet())
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
return targetObj;
}
public static JsonObject mergeInto(JsonObject targetObj, JsonObject defaultObj) {
for (Map.Entry<String, JsonElement> entry : defaultObj.entrySet()) {
if (targetObj.has(entry.getKey()) == false)
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
}
return targetObj;
}
public static JsonElement deepClone(JsonElement el){
if (el.isJsonPrimitive() || el.isJsonNull())
return el;
if (el.isJsonArray()) {
JsonArray array = new JsonArray();
for(JsonElement arrayEl: el.getAsJsonArray())
array.add(deepClone(arrayEl));
return array;
}
if(el.isJsonObject()) {
JsonObject obj = new JsonObject();
for (Map.Entry<String, JsonElement> entry : el.getAsJsonObject().entrySet()) {
obj.add(entry.getKey(), deepClone(entry.getValue()));
}
return obj;
}
throw new IllegalArgumentException("JsonElement type " + el.getClass().getName());
}
+1 to make the _deepCopy_ public. This feature is naturally expected to be provided by the gson library. There are lot of cases where you just want to take some your JsonObject as a source (or template) for your further manipulations(adding/removing properties, etc) but keeping the original untouched. with _deepCopy_ you don't need to reinvent a wheel in every of your projects. you simply use it out of the box.
Guys please make deepCopy public...
yes, it needs a way to clone. I prefer just implements Cloneable interface and just make it deepCopy.
I am open to it. Please send a pull request. Thanks.
On Thu, Nov 24, 2016 at 4:46 PM, Edgenius notifications@github.com wrote:
yes, it needs a way to clone. I prefer just implements Cloneable interface
and just make it deepCopy.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/google/gson/issues/760#issuecomment-262860512, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABCwyo9L5cUFXRmWwiM-EYOqVD1NcSHXks5rBi__gaJpZM4G7cBz
.
+1
I need JsonElement make deepCopy public for doing merge/extend 2 JsonObject.
+1 make it public
Do it already...
+1 need public
+1 My life would be easier if this were public.
I need to perform a large number of String substitutions to a copy of my JsonObject (and it's many children etc) while leaving the original as I found it.
Here's my workaround solution:
public class GsonUtils {
public static JsonObject deepCopy(JsonObject jsonObject) {
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
if (entry.getValue().isJsonObject()) {
result.add(entry.getKey(), deepCopy(entry.getValue().getAsJsonObject()));
} else if (entry.getValue().isJsonArray()) {
result.add(entry.getKey(), deepCopy(entry.getValue().getAsJsonArray()));
} else if (entry.getValue().isJsonPrimitive()) {
result.add(entry.getKey(), new JsonPrimitive(entry.getValue().getAsString()));
}
}
return result;
}
private static JsonArray deepCopy(JsonArray jsonArray) {
JsonArray result = new JsonArray();
for (JsonElement jsonElement : jsonArray) {
if (jsonElement.isJsonObject()) {
result.add(deepCopy(jsonElement.getAsJsonObject()));
} else if (jsonElement.isJsonArray()) {
result.add(deepCopy(jsonElement.getAsJsonArray()));
} else if (jsonElement.isJsonPrimitive()) {
result.add(new JsonPrimitive(jsonElement.getAsString()));
}
}
return result;
}
}
very useful function, will wait for it
It's public now, please close.
Most helpful comment
Guys please make deepCopy public...