Retrofit 2, converters and unwrapping json objects with RxJava
•
My two cents on how to deal with wrapped json objects by using Retrofit converters
I’m sure everyone has had the joy of dealing with wrapped objects in json. The best part of them is that you get to check for errors 3 times: IOException
, isSuccessful
, and the response’s custom result code, if you were to use the default Call<>
object provided by Retrofit 2.
Have a look at the following example:
The simple and straightforward approach to this object would look like the following and there is obviously some room for improvement.
You could go ahead and create your own Callback
and include handling of the response there calling your own methods to work with, but I prefer to use RxJava anyways, so let’s see how this would look.
Things seem a lot easier with RxJava: There’s error and next, but this is just my personal opinion. I generally like to use RxJava because test implementations of your service can be Observable.just(created)
very easily.
But obviously this doesn’t look right, either. There’s still error handling in onNext
where you just expect to be handling objects from your stream. RxJava has a lot of options that would offer to map this result and to properly handle those errors, but this is not the way I want to go.
I do not want to adapt my interface to the API. I just want an Observable<Person>
to subscribe to without further wrapping the Retrofit service or adding some custom response handling. Retrofit offers a powerful API that I can use to do just that: Return the plain, unwrapped object.
Using Retrofit converters
Retrofit offers the option to specify a converter that will parse the response into an object for you. GsonConverterFactory
is probably one of the more popular ones.
Since they handle the parsing of the response into objects, this is also where I want to hook in. The following describes how you could create your own converter to unwrap the API response in one place and to not have to deal with it in any other parts of your app.
If you find yourself asking Why would you do it that way? I have to say my reasoning is fairly simple: Abstraction. I can pack all of this API parsing and unwrapping code into a single package and hide it from the rest of the application. The only thing exposed to the rest of my app is a clean and easy to use interface.
Create a converter factory and handle the result
I do not want to reinvent the wheel. Gson offers powerful parsing of json objects and I can also create dynamic types. If I want my Person
I just have to tell Gson to parse the response as a WrappedResponse<Person>
and go on from there.
The code above wraps the gson factory and will use its implementation to parse the wrapped object. While we are handling Person
, the gson converter gets initialized to parse the WrappedResponse<Person>
. With this, all that’s left now is to properly read the data from the response as you can see below.
And this is basically all the magic to it. RxJava will handle the exception and my app can make use of a clean interface—it does not have to know anything about wrapped objects.
If we have a look at the result…
…this is how I prefer it.