使用Retrofit时手动解析部分响应

时间:2014-09-29 11:44:27

标签: android json gson retrofit

我正在使用一个REST API,它返回一个JSON文档,该文档以如下方式开始,并包含一个带有字符串ID(如“ABC”)的项目的“集合”。注意“routes”字段,其中包含一系列名为“ABC”,“ABD”,“ABE”等的字段,但是路由在json中不表示为数组,所以这些

{
"status":true,
"page":1,
"per_page":500,
"total_count":1234,
"total_pages":8,
"total_on_page":500,
"routes":{
    "ABC":[
    {
        "value":22313,
        <......>

我正在使用Retrofit,问题是routes字段不是一个数组(尽管事实上它肯定是这样)而且Retrofit / Gson要求我为具有字段变量abc,abd等的路由创建一个模型对象 - 这在数据变化时是不实际的。由于各种原因,更改服务器API很难,所以我希望在Android客户端上解决这个问题。

我认为这些是选项:

  • 在JSON文档到达Gson之前拦截它并调整文档,可能使用自定义的Gson解析器,或者拦截HTTP响应。

  • 绕过JSON解析,从Retrofit获取JSON文档(我还没弄明白如何做到这一点,或者是否有可能)

  • 使用我不知道的Retrofit的一些功能将字段名称映射到集合。

我很感激帮助,特别是如果有一种快速简便的方法可以解决这个问题。

2 个答案:

答案 0 :(得分:10)

事实证明,默认情况下Retrofit使用Gson可以很容易地添加自定义反序列化器来处理问题所在的JSON文档部分。

RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(ApiDefinition.BASE_URL)
        .setConverter(getGsonConverter())
        .build();

public Converter getGsonConverter() {
    Gson gson = new GsonBuilder()
            .registerTypeAdapter(RouteList.class, new RouteTypeAdapter())
            .create();
    return  new GsonConverter(gson);
}


public class RouteTypeAdapter implements JsonDeserializer<RouteList> {
    @Override
    public RouteList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Gson gson = new Gson();
        RouteList routeList = new RouteList();
        JsonObject jsonObject = json.getAsJsonObject();
        for (Map.Entry<String,JsonElement> elementJson : jsonObject.entrySet()){
            RouteList wardsRoutes = gson.fromJson(elementJson.getValue().getAsJsonArray(), RouteList.class);
            routeList.addAll(wardsRoutes);
        }
        return routeList;
    }

}

答案 1 :(得分:2)

在调用RestService之后,不要使用Model Name作为参数,您必须使用改进库中的Default Response类。

RestService方法

@FormUrlEncoded
    @POST(GlobalVariables.LOGIN_URL)
    void Login(@Field("email") String key, @Field("password") String value, Callback<Response> callback);

调用活动

中的方法
getService().Login(email, password, new MyCallback<Response>(context, true, null)
{
    @Override
    public void failure(RetrofitError arg0)
     {
        // TODO Auto-generated method stub
        UtilitySingleton.dismissDialog((BaseActivity<?>) context);
        System.out.println(arg0.getResponse());
      }

    @Override
    public void success(Response arg0, Response arg1)
    {
         String result = null;
         StringBuilder sb = null;
         InputStream is = null;
         try
         {
                is = arg1.getBody().in();
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null)
                {
                    sb.append(line + "\n");
                    result = sb.toString();
                    System.out.println("Result :: " + result);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    });