To serialize objects to JSON, we just create an instance of
Gson with the
GsonBuilder and use the
This will give us the result as a JSON String:
To convert this JSON back to a Java object, we use the
That’s pretty straight forward!
Serializing Object Hierarchies
Let us extend our structure with an abstract class
Plane and a
Bicycle POJO. The existing
Car also extends the
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
… we will get an
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
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.
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.