java-带翻新的StackExchange API处理

我正在编写一个简洁的Android应用程序以与API交互,这遵循了Google Android用户的体验.

该应用程序将使用Retrofit(使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);
}

最大的问题是,由于使用了通用包装器,我如何才能使Retrofit返回到List< Site>.无论如何,这可能同样适用于其他对象,例如“问题”,“答案”等.

在Chrome下使用Postman扩展程序进行测试后,我观察到以下内容,这是一个绊脚石,无论使用哪种REST-api,响应中都会返回通用包装器,但是JSON输出中的items字段包含数组在这种情况下的网站数量.

我推断出,在普通包装器中有一个未返回的字段,称为type.这里的想法是稍后再作弊…,因为它不是过滤器的一部分,这意味着必须创建一个新的过滤器通过/ filter / create API并将其作为对Retrofit的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(其值为answered here on SO)之后,我是否在这里遗漏了一些东西,这是我到目前为止所拥有的.

创建了一个名为SEWrapper.java的类,它像这样:

public class SEWrapper{
    @SerializedName("items") List<Class ?> mListItems;
    @SerializedName("type") String mJsonObjType;
}

在Site.java源代码中更改为使用SEWrapper而不是Site,并修改了REST调用.

这段代码改编自*上的问题,

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
       }
   }

关于如何解决这个绊脚石的想法不多.

从理论上讲,我可以将其重写以返回Retrofit的Response对象,并手动解析每个JSON对象以及创建该类型的Site列表,对于返回的每个API对象,它确实很麻烦且冗长.

我是用错误的方式这样做还是对Retrofit库设置了过高的期望?

解决方法:

当灯泡瞬间消失时,这个问题的答案非常简单.

我意识到,根据对stackexchange.com网站的API调用,项目列表可以引用任何对象,因此这意味着在对JSON的项目进行反序列化时应使用的一种类.

解决方案非常简单.

CommonSEWrapper.java:

public class CommonSEWrapper<T>{
   // snip
   @SerializedName("items") List<T> mListItems;
   // snip
}

然后,要申请Site对象,站点的REST API的接口将最终变为ISites.java:

public interface ISites{
   @GET("/sites")
    public void getAllSites(@Query("filter") String filterName, 
                            Callback<CommonSEWrapper<Site>> cbAllSites);
}

最后,通过Retrofit执行REST如下所示:

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!
   }
});

干净,优雅,简单,而且不会与Retrofit的魔法内乱交织.

希望这会帮助其他处于类似困境的人.

请享用.

上一篇:HG255D刷机OPENWRT笔记


下一篇:java-我可以在改造方法声明中使用varargs吗?