【问题标题】:Gson: Help me parse gson from serverGson:帮我从服务器解析 gson
【发布时间】:2018-10-19 08:02:28
【问题描述】:

调用API成功时的响应是:

{
    "meta": {
        "timestamp": "2018/05/16 16:43:21",
        "status": "OK"
    },
    "body": {....}

但在错误情况下调用上述相同 API 时的响应是:

{
    "meta": {
        "timestamp": "2018/08/16 15:52:45",
        "status": "VALIDATION_ERROR"
    },
    "body": [
        {
            "errorCode": "aaa",
            "errorMessage": "ERROR1",
            "property": "AAA",
            "args": "aa"
        }
    ]
}

可以看到响应体是diffrence,一个是Json数组,一个是json对象,如果我用retrofit怎么解析?

【问题讨论】:

  • api 将返回对象以及body 字段的数组?听起来很奇怪
  • 我想当响应成功时,我可以解析为模型成功,如果响应错误,我可以解析为模型错误
  • 那么你可能需要一个 TypeAdapter
  • TypeAdapter,这是什么?
  • 那是糟糕的 API 设计。如果可以(例如,如果它在内部),请尝试让 API 人员整合它。否则,您需要制作自己的 TypeAdapter。

标签: android json retrofit


【解决方案1】:

你的模型类应该是这样的 RootObject

public class RootObject
{
private Meta meta;

public Meta getMeta() { return this.meta; }

public void setMeta(Meta meta) { this.meta = meta; }

private ArrayList<Body> body;

public ArrayList<Body> getBody() { return this.body; }

public void setBody(ArrayList<Body> body) { this.body = body; }
}

public class Meta
{
private String timestamp;

public String getTimestamp() { return this.timestamp; }

public void setTimestamp(String timestamp) { this.timestamp = timestamp; }

private String status;

public String getStatus() { return this.status; }

public void setStatus(String status) { this.status = status; }
}

public class Body
{
private String errorCode;

public String getErrorCode() { return this.errorCode; }

public void setErrorCode(String errorCode) { this.errorCode = errorCode; }

private String errorMessage;

public String getErrorMessage() { return this.errorMessage; }

public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }

private String property;

public String getProperty() { return this.property; }

public void setProperty(String property) { this.property = property; }

private String args;

public String getArgs() { return this.args; }

public void setArgs(String args) { this.args = args; }
}

【讨论】:

  • 但是响应成功时的主体是对象,当错误是数组时,您的模型仅在响应错误时解析完成,但在响应成功时无法应用
【解决方案2】:

正如@Ridcully 所说,这是一个糟糕的 API 设计。由于您无法修改 API,解决方法是使用继承并将自定义 typeAdapter 添加到 Gson 实例。

请注意 SuccessResponseFailureResponse "is-a" Response。当您对Response 类使用typeAdapter 时,自定义反序列化器将根据Response.meta.status 的值来确定该对象应该被反序列化为SuccessResponse 类还是FailureResponse 类。

响应父类

public class Response{
     private Meta meta;

     public Meta getMeta(){ return meta; }
     public void setMeta(Meta meta){ this.meta = meta; }

}

成功响应子类

public class SuccessResponse extends Response{
     private SuccessContent body;

     public SuccessContent getSuccessContent() { return body; }
     public void setSuccessContent(SuccessContent content) { this.body = content }
 }

失败响应子类

public class FailureResponse extends Response{
     private List<FailureContent> body;

     public List<FailureContent> getBody() { return body; }
     public void setObjList(List<FailureContent> content) { this.body= content; }
}

成功内容类

public class SucessContent{
     //Model class of the success body
}

失败内容类

public class FailureContent{
     private String errorCode;
     private String errorMessage;
     private String property;
     private String args;

     public String getErrorCode() { return errorCode; }
     public void setErrorCode(String errorCode) { this.errorCode = errorCode; }

     public String getErrorMessage() { return errorMessage; }
     public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage;}

     public String getProperty() { return property; }
     public void setProperty(String property) { this.property = property; }

     public String getArgs() { return args; }
     public void setArgs(String args) { this.args = args; }

}

元类

public class Meta{
     private String timestamp;
     private String status;

     public String getTimestamp() { return this.timestamp; }
     public void setTimestamp(String timestamp) { this.timestamp = timestamp; }

     public String getStatus() { return this.status; }
     public void setStatus(String status) { this.status = status; }
}

用于反序列化响应类的 Gson 自定义类型适配器

public class ResponseBodyAdapter implements JsonDeserializer<Response> {
      @Override
      public Response deserialize (JsonElement json, Type typeOfT, JsonDerializationContext context) throws JsonParseException{
              JsonObject obj = json.getAsJsonObject();
              JsonObject metaObj = obj.getAsJsonObject("meta");
              String status = metaObj.get("status").getAsString();
              if(status.equals("OK")){
                 return context.deserialize(json, SuccessResponse.class);
              }else if(status.equals("VALIDATION_ERROR")){
                 return context.deserialize(json, FailureResponse.class);
              }
              return null;
        } 
 }

将类型适配器注册到 gson 并进行改造

Gson gson = new GsonBuilder()
                .registerTypeAdapter(Response.class, new ResponseBodyAdapter ())
                .create();
Retrofit retrofit = new Retrofit.Builder()
                       .baseUrl(baseUrl)
                      .addConverterFactory(GsonConverterFactory.create(gson))
                      .build();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 2018-08-12
    • 2021-08-23
    相关资源
    最近更新 更多