Java 使用改进型2转换器转换错误响应阵列

Java 使用改进型2转换器转换错误响应阵列,java,android,gson,retrofit2,Java,Android,Gson,Retrofit2,每当我得到错误时,错误主体如下所示: [ { "errorCode": 10001, "resource": null, "resourceId": null, "field": null, "parameter": null, "header": null, "allowedValues": null, "maxLength": null, "minLength": null } ] 错误主体是一个数组。我对许多API方法的成功有不同的看法,但错误数组

每当我得到错误时,错误主体如下所示:

[
 {
  "errorCode": 10001,
  "resource": null,
  "resourceId": null,
  "field": null,
  "parameter": null,
  "header": null,
  "allowedValues": null,
  "maxLength": null,
  "minLength": null
 }
]
错误主体是一个数组。我对许多API方法的成功有不同的看法,但错误数组响应是标准化的。我试过做很多事情

  • 使用泛型类型成功响应和错误响应数组生成包装类,并为此生成反序列化器,但我无法从类型变量和参数化类进行反序列化

  • 制作了一个ErrorDeserializer,但我不知道如何使用它进行错误响应

我完全可以在每次回调时序列化所有api方法的原始字符串,但我有太多的方法,我需要通用的解决方案。如果我没有解释清楚,请问我

我将添加我尝试过的示例(但这些示例并不完整):

响应包装类:

    public class ResponseWrap<T> {
        @Nullable
        private final T response;

        @Nullable
        private final List<ErrorResponse> errorResponses;

        public ResponseWrap(@Nullable T response, @Nullable List<ErrorResponse> errorResponses) {
            this.response = response;
            this.errorResponses = errorResponses;
        }
    }
错误反序列化程序:

    public class ErrorDeserializer implements JsonDeserializer<ArrayList<ErrorResponse>> {
        @Override
        public ArrayList<ErrorResponse> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
            Gson gson = new Gson();
            Type listType = new TypeToken<ArrayList<ErrorResponse>>(){}.getType();
            ArrayList<ErrorResponse> list = new Gson().fromJson(json, listType);
            final JsonArray jsonArray = json.getAsJsonArray();
            for (int i = 0; i < jsonArray.size(); i++) {
                ErrorResponse error = new ErrorResponse();
                JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();

                error.setErrorCode(jsonObject.get("errorCode").getAsInt());
                error.setResource(jsonObject.get("resource").getAsString());
                error.setResourceId(jsonObject.get("resourceId").getAsString());
                error.setField(jsonObject.get("field").getAsString());
                error.setParameter(jsonObject.get("parameter").getAsString());
                error.setHeader(jsonObject.get("header").getAsString());
                error.setAllowedValues(jsonObject.get("allowedValues").getAsString());
                error.setMaxLength(jsonObject.get("maxLength").getAsInt());
                error.setMinLength(jsonObject.get("minLength").getAsInt());

                list.add(error);
             }

             return list;
        }
    }
公共类ErrorDeserializer实现JsonDeserializer{
@凌驾
公共ArrayList反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext){
Gson Gson=新的Gson();
类型listType=newTypeToken(){}.getType();
ArrayList=new Gson().fromJson(json,listType);
final JsonArray JsonArray=json.getAsJsonArray();
for(int i=0;i
响应换行反序列化程序-不工作,2个错误:

  • List error=new Gson().fromJson(jsonObject.getAsJsonObject(“error”),ArrayList.class);//无法从参数化类中选择

  • T success=new Gson().fromJson(jsonObject,T.class);//无法从类型变量中选择

    public class ResponseWrapDeserializer<T> implements JsonDeserializer<ResponseWrap<T>> {
        @Override
        public ResponseWrap<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            // Get JsonObject
            final JsonObject jsonObject = json.getAsJsonObject();
            if (jsonObject.has("error")) {
    
                Gson gson = new GsonBuilder()
                        .registerTypeAdapter(typeOfT, new ErrorDeserializer())
                        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
                        .create();
    
                List<ErrorResponse> error = new Gson().fromJson(jsonObject.getAsJsonObject("error"), ArrayList<ErrorResponse>.class);
    
                return new ResponseWrap<T>(null, error);
            } else {
                T success = new Gson().fromJson(jsonObject, T.class);
                return new ResponseWrap<T>(success, null);
            }
        }
    }
    
    公共类ResponseWrapDeserializer实现JsonDeserializer{
    @凌驾
    公共响应包装反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
    //获取JsonObject
    final JsonObject JsonObject=json.getAsJsonObject();
    if(jsonObject.has(“error”)){
    Gson Gson=new GsonBuilder()
    .registerTypeAdapter(typeOfT,新的ErrorDeserializer())
    .setDateFormat(“yyyy-MM-dd'T'HH:MM:ss”)
    .create();
    List error=new Gson().fromJson(jsonObject.getAsJsonObject(“error”),ArrayList.class);
    返回新的ResponseWrap(null,错误);
    }否则{
    T success=new Gson().fromJson(jsonObject,T.class);
    返回新的ResponseWrap(成功,空);
    }
    }
    }
    
想法是这样使用它们:

@POST("Login")
Call<ResponseWrap<AccessTokenResponse>> Login(@Body LoginRequest request);
@POST(“登录”)
调用登录(@Body LoginRequest请求);
但是我不能,因为上面提到的原因


问题是:如何以通用方式处理使用Refught2的数组中的错误响应?

您不能编写
T.class
——这在Java中是非法的。为了克服这一限制,您必须自己创建一个
Type
实例,或者根据Gson提供的内容解析泛型类型参数。在第一种情况下,需要十几个JSON反序列化程序来绑定各种
ResponseWrap
参数化;而在第二种情况下,您可以自己简单地解析实际的类型参数。在调用站点,您可以使用
TypeToken
s——一种特殊的Gson机制,通过类型参数化定义类型参数。还请注意,您不必实例化内部
Gson
实例:这可能会相对昂贵(尤其是在顺序上),并且不尊重当前反序列化程序绑定的
Gson
配置-使用
JsonDeserializationContext
,因为它可以为您提供所需的一切(下游类型适配器除外)

下面的JSON反序列化程序使用第二种方法,因为我觉得它更方便

final类ResponseWrapJsonDeserializer
实现JsonDeserializer{
//此反序列化程序不保存任何状态,因此我们可以隐藏其实例化详细信息
私有静态最终JsonDeserializer responseWrapJsonDeserializer=新responseWrapJsonDeserializer();
//TypeToken中的类型实例似乎是完全不可变的,并且可以作为值类型处理,因此我们可以使它们成为静态的最终类型,以便重用(这是安全的)
私有静态最终类型errorResponseListType=new-TypeToken(){
}.getType();
私有响应WrapJSondeSerializer(){
}
//只是欺骗调用站点:如果调用站点请求一个特殊类型的反序列化器,我们总是返回同一个实例(它总是同一个实例,然而,这正是Java泛型的工作方式)
静态JsonDeserializer getResponseWrapJsonDeserializer(){
@SuppressWarnings({“rawtypes”,“unchecked”})
最终JsonDeserializer转换=(JsonDeserializer)responseWrapJsonDeserializer;
回浇;
}
@凌驾
公共响应包装反序列化(最终JsonElement JsonElement、最终类型类型、最终JsonDeserialization
@POST("Login")
Call<ResponseWrap<AccessTokenResponse>> Login(@Body LoginRequest request);
{
    "foo": [1, 2, 3]
}
[
    {"errorCode": 10001},
    {"errorCode": 10002}
]