I'm consuming an API from my android app, and all the JSON responses are like this:
{
'status': 'OK',
'reason': 'Everything was fine',
'content': {
< some data here >
}
The problem is that all my POJOs have a status
, reason
fields, and inside the content
field is the real POJO I want.
Is there any way to create a custom converter of Gson to extract always the content
field, so retrofit returns the appropiate POJO?
In my case, the "content" key would change for each response. Example:
In such cases I used a similar solution as listed above but had to tweak it. You can see the gist here. It's a little too large to post it here on SOF.
The annotation
@InnerKey("content")
is used and the rest of the code is to facilitate it's usage with Gson.@BrianRoach's solution is the correct solution. It is worth noting that in the special case where you have nested custom objects that both need a custom
TypeAdapter
, you must register theTypeAdapter
with the new instance of GSON, otherwise the secondTypeAdapter
will never be called. This is because we are creating a newGson
instance inside our custom deserializer.For example, if you had the following json:
And you wanted this JSON to be mapped to the following objects:
You would need to register the
SubContent
'sTypeAdapter
. To be more robust, you could do the following:and then create it like so:
This could easily be used for the nested "content" case as well by simply passing in a new instance of
MyDeserializer
with null values.You would write a custom deserializer that returns the embedded object.
Let's say your JSON is:
You'd then have a
Content
POJO:Then you write a deserializer:
Now if you construct a
Gson
withGsonBuilder
and register the deserializer:You can deserialize your JSON straight to your
Content
:Edit to add from comments:
If you have different types of messages but they all have the "content" field, you can make the Deserializer generic by doing:
You just have to register an instance for each of your types:
When you call
.fromJson()
the type is carried into the deserializer, so it should then work for all your types.And finally when creating a Retrofit instance:
Bit late but hopefully this will help someone.
Just create following TypeAdapterFactory.
and add it into your GSON builder :
or
Had the same problem couple of days ago. I've solve this using response wrapper class and RxJava transformer, which I think is quite flexiable solution:
Wrapper:
Custom exception to throw, when status is not OK:
Rx transformer:
Example usage:
My topic: Retrofit 2 RxJava - Gson - "Global" deserialization, change response type
As per answer of @Brian Roach and @rafakob i done this in the following way
Json response from server
Common data handler class
Custom serializer
Gson object
Api call