user-icon Balazs Baltringer
15. March 2017
timer-icon 3 min

Gson and Object Hierarchies

Gson is a small Java library for serializing objects into JSON and deserializing JSON back to java objects. But how can we deal with object polymorphism in Gson?

Serializing a Simple Object

Imagine a POJO named Car.


To serialize objects to JSON, we just create an instance of Gson with the GsonBuilder and use the toJson method.


This will give us the result as a JSON String: {"cargoCapacityInLiter":0}

To convert this JSON back to a Java object, we use the fromJson method.


That’s pretty straight forward!

Serializing Object Hierarchies

Let us extend our structure with an abstract class Vehicle, a Plane and a Bicycle POJO. The existing Car also extends the Vehicle class.


If we serialize instances of these three classes to JSON, …


… we get the following strings.


But here is the problem: How can we distinguish these objects during deserialization? The JSON strings have lost the type information. Is this string a Car or a Bicycle? Gson cannot infer that just from the field names. And if we try to deserialize an abstract Vehicle


… we will get an InstantiationException.

Preserving Runtime Type Information

The solution is to make the type information (e.g. what type of object we are serializing) available during deserialization by including it in the serialized string:


This is a common problem, so it is somewhat surprising that Gson does not already offer an option to do that. The Gson project on GitHub contains an additional library, gson-extras, which provides that functionality in form of TypeAdapters. However this library is not officially released and maintained.

We now have two options. We can locally install the gson-extras library by cloning the official GitHub repo and running mvn install. However, we saw failing tests and a pom.xml incompatibility with our version of Maven. The recommended alternative is to just copy what we need to our project. In our case, this is just RuntimeTypeAdapterFactory.java.

Next, we have to create a RuntimeTypeAdapterFactory of the base type Vehicle and register all subclasses of Vehicle, each with a descriptive label. We then create the Gson instance as we did previously, but this time we also let Gson know about our object hierarchy.


When we serialize now …


… a type field with the previously specified label is included in the JSON strings.


Now we can deserialize Vehicle instances without ambiguities. We only have to provide the abstract class as type parameter.


It was suprising that Gson doesn’t include handling object hierarchies in their core library. This makes such a routine task harder than expected.

If given a choice, we would generally prefer Jackson, which offers annotation-driven polymorphic de-/serialization out-of-the-box. The only annoyance with Jackson is that base class annotations have to reference the subtypes, which introduces circular dependencies and limits reuse. But that is a different topic and for another post.

A working example of the code used in this post is available on GitHub.

Comment article

Comments

  1. Balazs Baltringer

    The mentioned package is not resolved by gradle or maven?

  2. Prateek

    I am using above example in one of my OSGi bundle but com.google.gson.internal package is not getting resolved.