我正在编写与API交互的整洁应用程序,该应用程序遵循Google Android用户体验。
应用程序将使用改造(使REST-API机制更加容易)。
现在,我创建了与每个API调用对应的Java类。
例如,以这种方式处理/sites
API的Site.java
类:
这是简洁的:
public class Site{
@SerializedName("api_site_parameter") String mApiSiteParameter = "";
// snip
}
以这种方式连接接口,称为ISites.java
public interface ISites{
@GET("/sites")
public void getAllSites(@Query("filter") String filterName,
Callback<List<Site>> cbAllSites);
}
最大的问题是,由于使用了通用包装器,因此如何使改造返回List<Site>
集合,无论如何,这都可以同样适用于其他对象,例如Question
,Answer
等。
在Chrome下使用Postman扩展测试后,我观察到以下是一个绊脚石,在响应中返回了公共包装器,无论使用哪种REST-API,无论使用哪种REST-API,但是,JSON输出中的items
字段,在这种情况下包含Site
的数组。
我推论出来的是,普通包装器中有一个未返回的字段,称为 type
,这里的想法是在... 上作弊,因为它不是其中的一部分过滤器,这意味着必须通过/filter/create
API创建一个新的过滤器,并将其作为调用的一部分应用于改造的RestAdapter
调用,如:
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){
}
});
研究了GSON的自定义TypeAdapterFactory
之后,在这里回答了,我在这里错过了一些东西,这就是我到目前为止的。
创建了一个称为SEWrapper.java
的类,该类是这样的:
public class SEWrapper{
@SerializedName("items") List<Class ?> mListItems;
@SerializedName("type") String mJsonObjType;
}
在网站周围更改。Java源使用SEWrapper
而不是Site
,然后修改了其余的调用。
此代码是根据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是关于如何解决这个绊脚石的想法。
我可以将其重写以返回改装的Response
对象,并手动解析每个JSON对象,并创建该类型Site
的列表,它确实会为返回的每个API对象感到笨拙且漫长。
我是以错误的方式这样做,还是在改造库中设置了我的期望?
当灯泡瞬间熄灭时,这个问题的答案非常简单。
我意识到项目列表可以参考任何对象,具体取决于 stackexchange.com 网站的API调用,因此,这意味着类型的类型类应应当JSON的items
被估算时使用。
解决方案很简单。
commsewrapper.java :
public class CommonSEWrapper<T>{
// snip
@SerializedName("items") List<T> mListItems;
// snip
}
然后申请Site
对象,该网站REST API的接口最终会像这样, isites.java.java :
public interface ISites{
@GET("/sites")
public void getAllSites(@Query("filter") String filterName,
Callback<CommonSEWrapper<Site>> cbAllSites);
}
最后,通过改造的其余执行方式看起来像这样:
RestAdapter ra = new RestAdapter.Builder()
.setServer("http://api.stackexchange.com/2.1")
.build();
ISites sites = ra.create(ISites.class);
ra.getAllSites("", new Callback<CommonSEWrapper<Site>>(){
@Override
public void failure(RetrofitError argRetrofitError){
}
@Override
public void success(CommonSEWrapper<Site> sites, Response response){
// sites is filled in, just like magic!
}
});
干净,优雅和简单,没有弄乱改造的魔术的内部。
希望这将帮助其他发现自己经历过类似困境的人。
享受。