Gson: Populate existing object

Created on 19 Mar 2015  路  20Comments  路  Source: google/gson

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

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).

All 20 comments

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

  • Added labels: Type-Enhancement
  • Removed labels: Type-Defect
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 where it passes along the containing object as context mainly so it can choose to reuse the T hanging off of it and continue on.

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.

Was this page helpful?
0 / 5 - 0 ratings