java - GSON 忽略类型错误的元素

标签 java android json gson retrofit

我正在使用 Retrofit(结合 Ok​​Http 和 GSON)与在线网络服务进行通信。 网络服务有一个围绕它的所有响应的默认包装器,类似于:

{  
  "resultCode":"OK",
  "resultObj":"Can be a string or JSON object / array",
  "error":"",
  "message":""
}

在本例中,resultCode 将是 OKNO。此外,errormessage 只有在处理请求时发生错误时才有任何内容。最后但并非最不重要的一点是,resultObj 将包含调用的实际结果(在示例中是字符串,但有些调用返回 JSON 数组或 JSON 对象)。

为了处理这些元数据,我创建了一个通用类,如下所示:

public class ApiResult<T> {

    private String error;
    private String message;
    private String resultCode;
    private T resultObj;

    // + some getters, setters etcetera
}

我还创建了代表有时在 resultObj 中给出的响应的类,并且我定义了一个用于 Retrofit 的接口(interface),看起来有点像这样:

public interface SomeWebService {

    @GET("/method/string")
    ApiResult<String> someCallThatReturnsAString();

    @GET("/method/pojo")
    ApiResult<SomeMappedResult> someCallThatReturnsAnObject();

}

只要请求有效,这一切都可以正常工作。但是当服务器端发生错误时,它仍然会返回一个字符串类型的resultObj。这会导致 someCallThatReturnsAnObject 在 Retrofit RestAdapter/GSON 库中崩溃,并显示如下消息:

retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:

Expected BEGIN_OBJECT but was STRING at line 1 column 110 path $.resultObj

现在,最后,我的问题是:

  1. 是否有一种(简单的)方法可以告诉 GSON,如果它与预期的类型不匹配,它应该忽略(也称为“nullify”)一个属性?
  2. 我可以告诉 GSON 将空字符串视为 null 吗?

最佳答案

像这样定义你的模型:

public class ApiResult {

    private String error;
    private String message;
    private String resultCode;
    private MyResultObject resultObj;
}

然后,为 MyResultObject 创建一个 TypeAdapterFactory:

public class MyResultObjectAdapterFactory implements TypeAdapterFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if (type.getRawType()!= MyResultObject.class) return null;

        TypeAdapter<MyResultObject> defaultAdapter = (TypeAdapter<MyResultObject>) gson.getDelegateAdapter(this, type);
        return (TypeAdapter<T>) new MyResultObjectAdapter(defaultAdapter);
    }

    public class MyResultObjectAdapter extends TypeAdapter<MyResultObject> {

        protected TypeAdapter<MyResultObject> defaultAdapter;


        public MyResultObjectAdapter(TypeAdapter<MyResultObject> defaultAdapter) {
            this.defaultAdapter = defaultAdapter;
        }

        @Override
        public void write(JsonWriter out, MyResultObject value) throws IOException {
            defaultAdapter.write(out, value);
        }

        @Override
        public MyResultObject read(JsonReader in) throws IOException {
            /* 
            This is the critical part. So if the value is a string,
            Skip it (no exception) and return null.
            */
            if (in.peek() == JsonToken.STRING) {
                in.skipValue();
                return null;
            }
            return defaultAdapter.read(in);
        }
    }
}

最后,为Gson注册MyResultObjectAdapterFactory:

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(new MyResultObjectAdapterFactory())
    .create();

现在,当使用该 Gson 对象反序列化 ApiResult json 时,如果 resultObj 将被设置为 null是一个字符串

我希望这能解决你的问题 =)

关于java - GSON 忽略类型错误的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27212598/

相关文章:

java - 比较Json Array的对象并显示具有相同参数的对象

java - 为什么 CentOs 6 上的 Glassfish 3.1 不能服务端口 80?

java - 编写 hibernate 查询时遇到问题

java - 子类化并覆盖 onTouchEvent

java - JSON 字符串验证 [Spring Boot] - 约束零值

php - QT5 : best efficiant way to "unserialise" array of keys/values from json result

java - 如何确保Java类中的两个方法至少之一被重写?

Java Regex - 检查回车符

java - 安卓和时间

android - 如果设备语言是阿拉伯语,布局会发生变化