Retrofit 2:处理动态JSON响应

时间:2017-03-27 19:33:12

标签: android json rest retrofit2

我使用retrofit 2作为REST客户端,我无法弄清楚如何反序列化dynamic JSON response

根据状态值(成功或失败),我们的JSON可以在result字段中包含两个不同的对象:

  1. 成功的响应会返回User个对象:

    {
       "status": 200,
       "message": "OK",
       "result": {
          "id": "1",
          "email": "bla@bla.bla"
           ...
       }
    }
    
  2. 失败的响应会返回Error个对象:

    {
       "status": 100,
       "message": "FAILED",
       "result": {
          "error": "a user with this account email address already exists"
       }
    }
    
  3. 我创建了3个POJO类...

    1. APIResponse:

      public class APIResponse<T> {
          @Expose private int status;
          @Expose private String message;
          @Expose private T result;
          ...
      }
      
    2. 用户:

      public class User {
          @Expose private String id;
          @Expose private String email;
          ...
      }
      
    3. 错误:

      public class Error {
          @Expose private String error;
          ...
      }
      
    4. 以下是我打电话的方式:

      @FormUrlEncoded
      @PUT(LOGIN)
      Call<APIResponse<User>> login(@Field("email") String email, @Field("password") String password);
      

      以下是我的回复:

      @Override
      public void onResponse(Call<APIResponse<User>> call, Response<APIResponse<User>> response) {
         ...
      }
      
      @Override
      public void onFailure(Call<APIResponse<User>> call, Throwable t) {
         ...
      }
      

      问题:

      API call预计返回类型为Call<APIReponse<User>>。但是,它可能无法获得User对象...因此,如何修改此方法以接受APIResponse<User>APIResponse<Error>

      换句话说,如何对可以采用两种不同格式的JSON数据进行反序列化?

      我看过的解决方案:

      1. 包括错误&#39;用户类中的字段或扩展错误类(丑陋)。
      2. 自定义拦截器或转换器(难以理解)。
      3. 说服API开发人员改变它并让我的生活更轻松:)

2 个答案:

答案 0 :(得分:1)

我不确定该解决方案是否可行,但您可以尝试将<APIResponse<User>>更改为<APIResponse<Object>>

Call<APIResponse<Object>> login(@Field("email") String email, @Field("password") String password);

@Override
   public void onResponse(Call<APIResponse<Object>> call, Response<APIResponse<Object>> response) {
   //depending on the response status, you can cast the object to appropriate class
   Error e = (Error)response.body().getResult();
   //or
   User u = (User)response.body().getResult();
}

或其他替代方法,使用String而不是POJO

Call<String> login(@Field("email") String email, @Field("password") String password);

检索JSON并手动序列化或使用GSON

答案 1 :(得分:0)

您应该检查响应代码并使用所需的类来处理json