问题
I have an API response which is meant to generically return data for various activities of our application. In an effort to make the application as generic and flexible as possible we have setup an API to deliver a collection of URLs to utilize to create various rows on our activities. Our base object looks like:
public class BaseApiObject {
@SerializedName("apiVersion")
private String apiVersion = null;
@SerializedName("totalResults")
private Integer totalResults = null;
}
Our response for the activity looks like:
public class ActivityApiResponse extends BaseApiObject {
@SerializedName("results")
private List<ScreenItem> results = new ArrayList<>();
}
And the ScreenItem looks like:
public class ScreenItem extends BaseApiObject {
@SerializedName("apiUrls")
private List<String> apiUrls = new ArrayList<>() ;
}
I would like to be able to do something like this with retrofit:
@GET("{url}")
Call<? extends BaseApiObject> getUrl(@Path("url") String url);
We know that each request we make will return a BaseApiObject, but we are unsure of which type of object we will actually return -- and some of these URLs will return a list of many different types of objects.
We get the following error:
java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call<? extends com.company.BaseApiObject>
Is there a way with Retrofit to handle this scenario or do I need to return the BaseApiObject, and then use a custom gson deserializer to actually return the proper object type(s)?
回答1:
In the end, I ended up needing to create my own Deserializer. I took the JsonDeserializationContext and then parsed my elements based on the type which was returned in the json response.
For instance assume my json looked like:
{ "shapes":
[
{"type": "circle", "radius": 2},
{"type": "rectangle", "width": 3, "height": 2},
{"type": "triangle", "sides": [3, 4, 5]}
],
"apiVersion": "0.1.0",
"totalResults": "3"
}
In my deserializer, I would look at the type of the shapes in a loop, and do something like:
switch(jsonObject.get("type").getAsString()) {
case "circle":
return context.deserialize(jsonObject, Circle.class);
break;
case "rectangle":
return context.deserialize(jsonObject, Rectangle.class);
break;
case "triangle":
return context.deserialize(jsonObject, Triangle.class);
break;
default:
return context.deserialize(jsonObject, Shape.class);
break;
}
来源:https://stackoverflow.com/questions/37327048/retrofit-method-return-wildcard