It would be great is gson supported the population of existing objects. There
was a post a while back alluding to this behavior, but it doesn't exist now:
http://groups.google.com/group/google-gson/browse_thread/thread/ab97b754c1f3c53a
?pli=1
The rationale is that this would prevent users from having to create
TypeAdapters or InstanceCreators for every object that requires custom
construction, particularly since gson doesn't support the notion of a global
InstanceCreator at the moment.
Original issue reported on code.google.com by [email protected] on 8 Apr 2012 at 5:12
Note: This is an enhancement (didn't see a setting for this).
Original comment by [email protected] on 8 Apr 2012 at 5:13
Original comment by limpbizkit on 11 Apr 2012 at 8:33
It would be nice if it will be supported :)
http://stackoverflow.com/questions/12277765/it-is-possible-to-fill-current-objec
t-with-json-values-from-json
Original comment by [email protected] on 12 Feb 2013 at 9:03
what is the plan for this enhancement? is it on the roadmap?
Original comment by dominik.mengelt on 12 Nov 2013 at 1:34
I really like to see this enhancement. I am using the library in my Android
app. I have a ViewPager with existing items, when a page becomes visible, I
pull additional items remotely and I would like to populate the additional
fields in the existing items.
Original comment by [email protected] on 26 Nov 2013 at 9:50
Any update on this?
Any chance that it will ever be implemented? any body have a nice work around?
I'm starting a new project and can choose to use Jackson vs GSON, and I'm
deeply interested in the ability to update existing instance rather than always
creating new instance.
I'm thinking of creating a new object and then merging to the existing one
using reflexion but I would rather have this handle at the deserialization
layer.
Original comment by [email protected] on 13 Jan 2015 at 10:26
See Inderjeet Singh's answer in this thread:
https://groups.google.com/d/msg/google-gson/q5e3VMHzxTo/DOivwaGC2XoJ
I use the InstanceCreator solution and it works very well. It is far from ideal
as it requires creating a new Gson instance every time, but it works quite well.
Here is my function :
public static <T> void populate(GsonBuilder builder, JsonObject json, Class<T> type, T into) {
builder.registerTypeAdapter(type, new InstanceCreator<T>() {
@Override public T createInstance(Type t) { return into; }
}).create().fromJson(json, type);
}
Original comment by [email protected] on 15 Jan 2015 at 2:51
Something like this seems to work well for me. I might have missed something but so far, so good...
/**
* updates @target object from the @json object. Only fields existing in @json are affected
* @param target
* @param json
* @throws Exception
*/
public static void update(Object target, JsonObject json) throws Exception {
Class<? > class1 = target.getClass();
Set<Entry<String, JsonElement>> entrySet = json.entrySet();
for (Entry<String, JsonElement> entry : entrySet) {
String key = entry.getKey();
Field field = class1.getField(key);
Type genType = field.getGenericType();
field.set(target,
gson.fromJson(entry.getValue(),genType));
}
}
For the love of source do NOT use the snippet above as is.
But yes - This is a much needed feature. Just came across a very unfortunate use case.
Any update on this?
Why this issue was closed? is this became a planned feature? is it rejected?
You can implement this using InstanceCreators.
final Foo existing;
InstanceCreator<Foo> creator = new InstanceCreator<Foo>() {
public Foo createInstance(Type type) { return existing; }
}
Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class, creator).create();
Foo value = gson.fromJson(jsonString, Foo.class);
// value should be same as existing
I needed to update a managed JPA object with a JSON from the web service, this is the solution I've found (I needed to use the local instance of appConfig):
AppConfiguration appConfig = AppConfigurationDAO.getInstance().read(Long.parseLong(req.params(":id")));
InstanceCreator<AppConfiguration> creator = new InstanceCreator<AppConfiguration>() {
private AppConfiguration appConfig;
public AppConfiguration createInstance(Type type) {
return appConfig;
}
public InstanceCreator<AppConfiguration> withValue(AppConfiguration appConfig) {
this.appConfig = appConfig;
return this;
}
}.withValue(appConfig);
Gson gson = new GsonBuilder().registerTypeAdapter(AppConfiguration.class, creator).create();
appConfig = gson.fromJson(req.body(), AppConfiguration.class);
return AppConfigurationDAO.getInstance().update(appConfig);
I then stated to wonder: can't we have a InstanceUpdater class? It could have a implementation like this:
import com.google.gson.InstanceCreator;
import java.lang.reflect.Type;
public class InstanceUpdater<T> implements InstanceCreator<T> {
private T object;
public T createInstance(Type type) {
return object;
}
public InstanceUpdater(T object) {
this.object = object;
}
}
Then I can use with something like this:
InstanceCreator<AppConfiguration> creator = new InstanceUpdater<AppConfiguration>(appConfig);
But I'm not sure, I feel there may be a better way of doing this, and it would be amazing to have something inside Gson to manage this for me.
Why this issue was closed? is this became a planned feature? is it rejected?
@Robertiano At the moment there is a workaround as outlined above with InstanceCreator.
We are still searching for an elegant proposal.
Apparently i need this as well, InstanceCreator is a bad option as if i want to make an extendable class static creators will need to be overwritten since there is no inheritance for that.
Typeadapter creates the object, i seriously think that only copying field without object creation should be easy, if not at least can you supply a static method that can copy the fields using reflection ?
TypeAdapter (example code) worked well for populating an existing object. Just return the instance in the read method.
Would love to see this, too.
I've been looking for this functionality for years. @inder123 said "We are still searching for an elegant proposal."
What's wrong with something like gson.fromJson(existingObject, json) ? I don't see why it would not cover the same use cases as gson.fromJson(json).
For posterity, if this is ever addressed:
Take into account nested reuse of existing objects at any level of the deserialization, not just the root object. Then you can see why InstanceCreator doesn't work.
You would need to pass in the containing object (which itself went through the usual process to be obtained), perhaps the InstanceUpdater
I have use cases (multiple) where I have all sorts of state like event handlers hanging off of important levels of a large tree of objects, and I want essentially all the unimportant "leaf fields" overwritten with incoming values but the important object scaffolding itself remains unchanged at all levels.
This is one of those things that is pretty easy to imagine how to implement it inside Gson, but hard to impossible to do from the outside looking in.
Most helpful comment
I've been looking for this functionality for years. @inder123 said "We are still searching for an elegant proposal."
What's wrong with something like gson.fromJson(existingObject, json) ? I don't see why it would not cover the same use cases as gson.fromJson(json).