I am in the process of writing a neat Android application to interact with the API, that follows the Google Android user experience.
The application will be using Retrofit (to make REST-api mechanisms easier).
Now, I have created Java classes that corresponds to each API call.
For example, Site.java
class that handles the /sites
API in this fashion:
This is condensed for brevity:
public class Site{
@SerializedName("api_site_parameter") String mApiSiteParameter = "";
// snip
}
The interface is wired up in this fashion, called ISites.java
public interface ISites{
@GET("/sites")
public void getAllSites(@Query("filter") String filterName,
Callback<List<Site>> cbAllSites);
}
The big question is, since the common wrapper is used, how can I make Retrofit return back a List<Site>
collection regardless, this could equally apply to other objects such as Question
, Answer
and so on.
After testing with Postman extension under Chrome, I observed the following, which is a stumbling block, the common wrapper is returned in the response, regardless of which REST-api to use, however, the items
field within the JSON output, contains the array of Site
in this case.
I deduced, that there's a field in the common wrapper that is not returned, called type
The idea here is to cheat a little bit later on... and, since it's not part of the filter, which meant having to create a new filter via /filter/create
API and apply that as part of invocation to the Retrofit's RestAdapter
call, as in:
RestAdapter ra = new RestAdapter.Builder()
.setServer("http://api.stackexchange.com/2.1")
.setLogLevel(LogLevel.FULL)
.build();
ISites sites = ra.create(ISites.class);
sites.getAllSites("my_commonwrapper_filter", Callback<Site>(){
@Override
public void failure(RetrofitError argRetrofitError){
}
@Override
public void success(List<Site> sites, Response response){
}
});
After studying the Gson's custom TypeAdapterFactory
which was answered here on SO, am I missing something here, this is what I have so far.
Created a class called SEWrapper.java
which went like this:
public class SEWrapper{
@SerializedName("items") List<Class ?> mListItems;
@SerializedName("type") String mJsonObjType;
}
Changed around the Site.java source to use SEWrapper
instead of Site
, and modified the REST call.
This code which is adapted from the question on StackOverflow,
private class SEWrapperTypeAdapterFactory extends CustomizedTypeAdapterFactory<SEWrapper> {
private SEWrapperTypeAdapterFactory() { super(SEWrapper.class); }
@Override
protected void beforeWrite(SEWrapper source, JsonElement toSerialize) {
// Ignored for now as all this is Read Only operation!
}
@Override
protected void afterRead(JsonElement deserialized) {
String typeOfJsonObj = deserialized.getAsJsonObject().get("type").getAsString();
if (typeOfJsonObj.equalsIgnoreCase("site")){
JsonArray jSiteArray = deserialized.getAsJsonObject().get("items").getAsJsonArray();
// Convert that to List<Site> type which I cannot figure out
}
}
Am out of ideas on how to get around this stumbling block.
I could, in theory, rewrite it to return a Retrofit's Response
object and manually parse each JSON object along with creating a List of that type Site
, it does feel cumbersome and long-winded for each of the API object returned.
Am I doing this the wrong way or have I set my expectations a little bit too high with the Retrofit library?