GSON deserialization: how to recognize objects?

I am trying to use gson library to deserialize a stream of objects I sent. In all the examples that I saw when the fromJson method is called, we already know what type of object we expect to have.

In my case, I get a stream of different objects, and I would like to know how best to learn the classes of objects before deserializing them.

{ A : {...}, B : { B1 : {...}, B2 : {...} }, C : {...} } 

In this example, I would like to know that 3 objects were sent to me: A.class, B.class and C.class

thanks

+4
source share
3 answers

The documentation contains examples of deserialization using arbitrary classes or two passes (the first general deserialization in the collection, and then the deserialization of the content).

This example looks exactly as you need. You can adapt it to use

 JsonObject obj = parser.parse(json).getAsJsonObject(); 

to get a JsonObject instead of an array so that you can iterate through all the properties (using entrySet ) and deserialize according to the names ( a = gson.fromJson(myjsonelement, A.class); ) just matching the names with the classes.

+6
source

Yes, I also came across this problem. It is not possible for gson to determine the actual class of the field value. It just tries to instantiate the class used to define the field. Needless to say, this is often not what we want. so if you said

 class C { private A a; private A c; } class B extends A { } 

then at runtime you

 C c; ca = new B(); cc = new B(); 

after deserialization, what you get is

 cagetClass()==A.class; cbgetClass()==A.class; 

so you will need to specify the subclass explicitly. Here is a wrapper class that is handy for gson.

 public class S<T> { private String objectClass; private String rawObjectRepresentation; // Gson needs no args constructor public S() { } public S(T obj) { objectClass = obj.getClass().getName(); rawObjectRepresentation = getGson().toJson(obj); } @SuppressWarnings("unchecked") public T extract() throws ClassNotFoundException { final Class<?> clazz = Class.forName(objectClass); return (T)getGson().fromJson(rawObjectRepresentation, clazz); } private Gson getGson() { return new GsonBuilder().create(); } @Override public String toString() { return "type:"+objectClass; } } 
+2
source

If there is a field on the json object that you can use to identify the subclass you need to use, you can use Gson on Fire: https://github.com/julman99/gson-fire

It has a function called Type Selector that does exactly what you need.

Imagine a base class and two child classes, A and B, then the code would look like this:

 GsonFireBuilder builder = new GsonFireBuilder() .registerTypeSelector(Base.class, new TypeSelector<Base>() { @Override public Class<? extends Base> getClassForElement(JsonElement readElement) { String kind = readElement.getAsJsonObject().get("kind").getAsString(); if(kind.equals("a")){ return A.class; //This will cause Gson to deserialize the json mapping to A } else if(kind.equals("b")) { return B.class; //This will cause Gson to deserialize the json mapping to B } else { return null; //returning null will trigger Gson default behavior } } }); Gson gson = builder.createGson(); 
+2
source

All Articles