Retrofit Error: How would I go about deserializing any kind of response from the server?

Retrofit Error: How would I go about deserializing any kind of response from the server?

我正在为 android 使用改造,效果很好,但我想知道是否有更好的解决方案来解决我的问题。

背景

所以我有一个后端服务器,它可能会以 JSON 形式(不是网络)响应与服务器相关的错误消息,例如 "could not find ID X" 等

看起来像这样

{
      "data": {
        "errors": {
          "base": [
            "You could do the following because of blah blah"
          ]
        }
      }
    }

所以问题是 JSON 包含数组 "base" 的错误对象 可能不会被称为 "base" 它可以被称为完全不同的东西 。我的后端有很多种错误响应消息名称,不能轻易更改。

我的问题是,可以反序列化这个 JSON 数组而无需事先知道它的名称。

到目前为止,我一直在做这件事,这让我很痛苦。

public class MyRetrofitError
{

    @SerializedName(JsonConstants.ERROR_KEY)
    private Errors errors;


    public Errors getErrors() {
        return errors;
    }

    public void setErrors(Errors errors) {
        this.errors = errors;
    }

    public static class Errors
    {
        private String errorMessage;
        private ErrorCodes errorCodes;

        public enum ErrorCodes{
            BOOKED_OVER_20,PROMO_CODE_FAILED;
        }

        @SerializedName("booked_over")
        private ArrayList<String> bookedOver= new ArrayList<String>();

        @SerializedName("promo_fail")
        private ArrayList<String> promoFailed= new ArrayList<String>();

        public String getErrorMessage() {
            if(promoFailed!= null && promoFailed.size() > 0) {setErrorMessage(promoFailed().get(0)); errorCodes = ErrorCodes.PROMO_CODE_FAILED;}
            if(bookedOver!= null && bookedOver.size() > 0){setErrorMessage(bookedOver().get(0)); errorCodes = ErrorCodes.BOOKED_OVER_20; }

            return errorMessage;
        }

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

        public ErrorCodes getErrorCodes() {
            return errorCodes;
        }
    }


}

请注意:根 "data" 对象不存在于此,它在其他地方通过泛型处理,所以我在这个问题中省略了它

然后我将使用改造错误 class getBodyAs 方法将传入的错误映射到此模型。

他们的方法更好吗?请注意后端是我无法控制的。

假设您将 Gson 与 Retrofit 一起使用(这是默认设置)。您可以为您的错误 class 写一个 Custom Gson Deserializer 并根据需要保存。

这是一个简单的例子来给你这个想法(未经测试)

// Possible error class
public static class Errors {
  Map<String, List<String>> errors;
  public void addErrors(String key, List<String> issues) {
     errors.put(key, issues);
  }
}

class ErrorDeserialzer implements JsonDeserializer<Errors> {

  @Override
  public Errors deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
  throws JsonParseException {
    Set<Map.Entry<String, JsonElement>> entries = jsonElement.getAsJsonObject().entrySet();
    for (Map.Entry<String, JsonElement> issues : entries) {
        List<String> values = new ArrayList<>();
        for (JsonElement value : issues.getValue().getAsJsonArray()) {
            values.add(value.getAsString());   
        }
        errors.add(issues.getKey(), values);
    }
    return errors;
  }
}

编辑 我也刚找到这个 link 可能会有帮助