Gson Custom Interface Adapter

Ezra Lazuardy
Feb 7 · 6 min read

Yesterday, before I write this article, I was facing a problem when trying to Serialize and Deserialize a JSON to an object using Gson.

I was confused at that time, because for somehow, my Gson can’t convert a JSON response to an object model.

The Use Case

Actually, my use case is simple. I have an object named OutItems that implement an Items interface. And I just need to convert a JSON like this :

To be deserialized to the OutItems object :

Item interface
OutItem object, implement an Item interface
Items (collection of Item) interface
OutItems (collection of OutItem) object, implement an Items interface

But as you can see, my object is a bit complicated. The OutItems have a list property to store a collection of OutItem object. And the reason why I use Item type in the list property is because OutItem implement an Item interface. In OO paradigm, this can be done because of the polymorphism concept.

Crafting The Code

I use Retrofit for the HTTP API and Gson for parsing the JSON response. After some time following the official documentation, I’ve got everything I need :

Retrofit client object
RemoteDatabase object, to create the DAO instance
OutItemsDao interface, to access the HTTP API endpoint, and return the response (object)

By the way, I’m just showing you the part of code that I think it’s important for this problem. I’m not gonna show you the entire code.

It was throwing a RuntimeException

After applying the code above, for somehow, my app is throwing a RuntimeException error, saying that it’s unable to invoke no arguments constructor for my interface.

Same error, different use case. I found this picture on technology.finra.org

FYI, this is not my first time using the Retrofit + Gson stuff. I’ve use it many times, and it works as usual with just applying my code above. But usually, I don’t use interface, just a plain object with no implement to any interface.

I think, this problem occurs because my object is too complicated for Gson to parse it. The problem is the polymorphism. Gson is confused about the data type that it should return and/or it can’t decide to parse it into what type.

In case you confused about what polymorphism is, I’ll give you simple explanation. In object oriented programming, polymorphism is the ability of an object to take on many forms.

Take a example of Car Interface and Toyota Object. If we implement the Car Interface to the Toyota Object, we can say that now Toyota is a Car, and so on. Instead of method returning a Toyota type explicitly, we can change that method to return a Car type, because Toyota is now identified as a Car. This feature can be powerful and at the same time, it’s a disaster when facing with third party library than only support explicit object type.

Photo by chuttersnap on Unsplash

Ok, back to this problem. As you can see, I have several objects and interfaces. OutItem that implement Item and the collection of Item called OutItems that implement Items. But Gson don’t have way to identify which Items object we are trying to deserialize. Gson be like :

“Hey, what type that should I return? Items or OutItems?, you’ve explicitly declare to return Items type but why the f you use it like an OutItems?!”

“Ah here we go again, how the f I convert a collection of Item to be a collection of OutItem?!”

Finally.., Gson dude is mad, and throw the exception right in my face.

But at least this dude is giving me some hint. In the error message, it’s clearly said that this problem can be resolved by using Gson InstanceCreator. For the first time, that’s look promising.

The Bad about InstanceCreator

After some time searching about InstanceCreator and how to register it, I realize that InstanceCreator really can resolve this problem. Yay!.

But, the bad news is.., this InstanceCreator is used for specific object type. Take a look at the example code below :

// object class
public class Id<T> {
private final Class<T> clazz;
private final long value;
public Id(Class<T> clazz, long value) {
this.clazz = clazz;
this.value = value;
}
}
// instance creator class
class IdInstanceCreator implements InstanceCreator<Id> {
public Id createInstance(Type type) {
return new Id(Object.class, 0L);
}
}
// applying to gson
Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();

The InstanceCreator class have createInstance() method that will return a explicit object type. This mean, we have to create an InstanceCreator for each of our object that we have.

Photo by Matt Hearne on Unsplash

This is just pain in the ass. And the worst thing is, this will lead to combinatorial explosion, or in OO programming, we call it class explosion. The condition where you have many different classes that makes everything much more complex and difficult to manage.

I’m not gonna use it, because I have many object that will implement a same interface. I need a better solution.

A Tricky Solution

I’ve search so much workaround about this problem, and seems nothing work perfectly. For example, I found a solution created by Finra Technology

But to use this solution, I need to reformat my JSON to be looking like this :

This mean that I need to declare explicitly what target class name that need to be deserialized in CLASSNAME property, and the actual object data goes inside the DATA property. This is kinda tricky solution because it have many flaw and vulnerability, and the worst case is resulting in ClassNotFoundException. I’m not gonna do it.

I need a solution that can be applied in a abstract and flexible way. This is where I start to build my own solution that best suit this problem.

My Own Solution

After spending some hours, I decided to use InterfaceAdapter to resolve this problem.

I’ve create my custom InterfaceAdapter that will handle serialize and deserialize process for my Gson. This class need a targetClass parameter, that takes any class as a target for the deserialize method return type. This mean that deserialize() will return a same type as targetClass that have been specified.

With this workaround, I don’t have to create a InstanceCreator for each of my object, because the InterfaceAdapter will handle all kind of object class. This class also support serializing process, make many things so much easier and manageable.

And the last thing to do is to apply my custom InterfaceAdapter to Retrofit.

Eureka!

Photo by Agnieszka Boeske on Unsplash

Finally, It’s working.

You know what?, I’m satisfied to know that my solution is really resolve this problem flawlessly. Maybe this solution is not perfect, but at least it’s working for me and I’m proud of that. Now I can fetch JSON and parse it into my object with or without using polymorphism.

Applying a polymorphism to your object is optional tho. But there is a good and benefit if you do that. It can help you structurize your object, return an object abstractly, and also optimizing code reuse. You should really consider the pros of polymophism if you’re an OO programmer.

I hope my solution is helping you too, whoever read this article. Cheers!.

Ezra Lazuardy

Written by

A lifelong learner, and perhaps.., a software engineer. Documenting all of my learning processes here. Find me on https://ezralazuardy.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade