You have a couple of options here. You can either use a custom serialiser/deserialiser, type adapters, or you can simply use pojos and unwrap the result yourself.
Let me start with the easiest solution I can think of. Picture you have these classes:
public class ResponseData<T> {
@SerializedName("status")
@Expose
String status;
@SerializedName("response")
@Expose
T response;
public T getResponse() {
return response;
}
// getters and setters and friends
}
public class Token {
@SerializedName("token")
@Expose
String token;
@SerializedName("expires")
@Expose
Timestamp expires;
public Token(String token, String expires) {
this.token = token;
this.expires = expires;
}
}
So one first thing to notice is the use of @Expose. This is a nice to have, but not extremely necessary. It helps you out when you have custom serialisers.
I assumed that you can have multiple api endpoints that return the same kind of body, where the json is:
{
"status":"success",
"response":{
// Can be anything
}
}
And as you can see the response can be anything.
You can then make your retrofit calls return ResponseData<Token> and in your callbacks you can check the value of status and see if you can do getResponse to unpack the result. The advantage of this approach is that you can reuse ResponseData fairly easily.
Another approach is to use custom serialisers or type adapters. This is in my opinion more laborious, but still a valid approach. I think the answer here is quite extensive and explains how you can do this to get the nested object inside response.
To prepare retrofit to use the type adapters, you'll need to inject a configured Gson instance into it. Here's how:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Token.class, new YourTypeAdapter())
.create();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
// ....
As you can see, we pass the created gson with your type adapter to the GsonConverterFactory used by retrofit. This prepares retrofit to serialise and deserialise Token objects using the given type adapter.
I think the main disadvantage with this approach is that if you want to write a generic deserialiser/serialiser/typeadapter it can become complicated quite fast (assuming you won't have only a Token object).