Deserialize ImmutableMap

1,332 views
Skip to first unread message

Fabian Zeindl

unread,
May 7, 2013, 6:30:01 AM5/7/13
to googl...@googlegroups.com
Hi,

 how to I deserialize an ImmutableMap with correct types and complex map-keys in gson?
From http://stackoverflow.com/questions/13623175/deserialize-to-an-immutablemap-with-gson I added the following TypeAdapterFactory and InstanceCreator, but it doesn't work (error below).

public static class ImmutableMapTypeAdapterFactory implements TypeAdapterFactory {

    @Override

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

        if (!ImmutableMap.class.isAssignableFrom(type.getRawType())) {

            return null;

        }

        final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

        return new TypeAdapter<T>() {

            @Override

            public void write(JsonWriter out, T value) throws IOException {

                delegate.write(out, value);

            }


            @Override

            @SuppressWarnings("unchecked")

            public T read(JsonReader in) throws IOException {

                return (T) ImmutableMap.copyOf((Map<?, ?>) delegate.read(in));

            }

        };

    }

}


public static <K,V> InstanceCreator<Map<K, V>> newMapInstanceCreator() {

    return new InstanceCreator<Map<K, V>>() {

        @Override

        public Map<K, V> createInstance(Type type) {

            return Maps.newHashMap();

        }

    };

}


Error:

2013-05-07 12:29:26,298 [Thread-4] ERROR org.gsonrmi.GsonRMIClientAdapter - Failed to invoke com.google.common.collect.ImmutableMap() with no args

java.lang.RuntimeException: Failed to invoke com.google.common.collect.ImmutableMap() with no args

at com.google.gson.internal.ConstructorConstructor$2.construct(ConstructorConstructor.java:94)

at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:168)

at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:146)

at at.busta.rsystem.common.GsonUtils$ImmutableMapTypeAdapterFactory$1.read(GsonUtils.java:119)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)

at com.google.gson.Gson.fromJson(Gson.java:795)

at com.google.gson.Gson.fromJson(Gson.java:859)

at com.google.gson.Gson$2.deserialize(Gson.java:131)

at at.busta.rsystem.common.dbobjects.Order$Deserializer.deserialize(Order.java:67)

at at.busta.rsystem.common.dbobjects.Order$Deserializer.deserialize(Order.java:1)

at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)

at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)

at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)

at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)

at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)

at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)

at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:146)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)

at com.google.gson.Gson.fromJson(Gson.java:795)

at com.google.gson.Gson.fromJson(Gson.java:859)

at org.gsonrmi.GsonRMIClientAdapter$Handler.invoke(GsonRMIClientAdapter.java:88)

at com.sun.proxy.$Proxy0.getOrdersList(Unknown Source)

at at.busta.rsystem.client.rmi.OrderLoader.load(OrderLoader.java:20)

at at.busta.rsystem.client.rmi.ListManager.loadNext(ListManager.java:266)

at at.busta.rsystem.client.rmi.ListManager.load(ListManager.java:236)

at at.busta.rsystem.client.rmi.DataLoader$LoadThread.runChecked(DataLoader.java:430)

at org.appkit.concurrent.LoggingRunnable.run(LoggingRunnable.java:14)

at org.appkit.concurrent.SmartRunnable.run(SmartRunnable.java:74)

at org.appkit.concurrent.SmartExecutor$Scheduler$1.run(SmartExecutor.java:158)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

Caused by: java.lang.InstantiationException

at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)

at java.lang.reflect.Constructor.newInstance(Constructor.java:525)

at com.google.gson.internal.ConstructorConstructor$2.construct(ConstructorConstructor.java:91)



Regards

Fabian Zeindl

Martin Grajcar

unread,
May 7, 2013, 6:41:11 AM5/7/13
to googl...@googlegroups.com
I don't think you InstanceCreator is of any use, as it creates a new HashMap, which works anyway. But I can see it in the answer, so I'm not sure at all.

For a different approach using JsonDeserializer see http://stackoverflow.com/a/7773201/581205.  I've tried both ways and finally decided to use the the deserializer (I don't recall why).


--
You received this message because you are subscribed to the Google Groups "google-gson" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-gson...@googlegroups.com.
To post to this group, send email to googl...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-gson?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Fabian Zeindl

unread,
May 7, 2013, 7:42:46 AM5/7/13
to googl...@googlegroups.com
Seems to work fine. Thank you!

Fabian Zeindl
> You received this message because you are subscribed to a topic in the Google Groups "google-gson" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-gson/Hw40o1rtBpI/unsubscribe?hl=en.
> To unsubscribe from this group and all its topics, send an email to google-gson...@googlegroups.com.

Joel Leitch

unread,
May 15, 2013, 10:42:43 AM5/15/13
to googl...@googlegroups.com
FWIW,
The original example would likely work if you changed the type that is passed into the "getDelegateAdapter" method to be a Map type instead of an ImmutableMap type. As well, the InstanceCreator would not be necessary if you do that.

For example, change:
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

to

// Should probably put in some check in case ImmutableMap is not parameterized.
Type[] arguments = ((ParameterizedType) type).getActualArguments();
Type mapType = Types.newParameterizedType(Map.class, arguments);
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, mapType);
Reply all
Reply to author
Forward
0 new messages