java - 不为空值调用 Gson 自定义解串器

标签 java gson deserialization

我在 JavaFX 上下文中使用 Gson 序列化。为了避免在我的序列化 Json 中使用属性样板,我创建了一些自定义序列化器/反序列化器来写入属性的值而不是实际的属性对象,特别是这个通用的 Property<T>。 :

private static class PropertySerializer implements JsonSerializer<Property<?>> {
    @Override
    public JsonElement serialize(Property<?> property, Type type, JsonSerializationContext context) {
        Object value = property.getValue();
        return context.serialize(value);
    }
}

private static class PropertyDeserializer implements JsonDeserializer<Property<?>> {
    @Override
    public Property<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (json.isJsonNull()) {
            System.out.println("I am never printed");
        }
        Type typeParam = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
        Object obj = context.deserialize(json, typeParam);
        return new SimpleObjectProperty<>(obj);
    }
}

在我偶然发现空值之前,它工作得很好。按照设计,当属性的值为 null(不是属性本身)时,我的序列化程序将写入 null,因为它写入的是值,而不是属性(我使用 Gson.serializeNulls() 使其实际写入它)。

我的问题是,在反序列化时,由于 a Gson bug我的自定义序列化程序未针对空值调用com.google.gson.TreeTypeAdapter 中的这些行引起:

@Override public T read(JsonReader in) throws IOException {
    if (deserializer == null) {
        return delegate().read(in);
    }
    JsonElement value = Streams.parse(in);
    if (value.isJsonNull()) {
        return null; // bypasses my custom deserializer! Why you do dat to me?
    }
    return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext);
}

导致属性本身在反序列化后为 null,而不是包含 null 值的非 null 属性。


他们将错误标记为已修复,因为显然有一个使用 TypeAdapterFactory 的解决方法,但我似乎无法弄清楚该怎么做。看起来我必须手动反序列化对象,但我不知道它的类型所以我不能。 TypeAdapter方法 readwrite不要给我提供 JsonDeserializationContext我目前的 Gson ,所以我不能依赖它的标准反序列化来获取我的值(我使用自定义反序列化器很容易做到这一点)。

private static class PropertyTypeAdapter extends TypeAdapter<Property<?>> {

    @Override
    public void write(JsonWriter out, Property<?> value) throws IOException {
        Object valueToSerialize = value.getValue();
        // how to use standard serialization of my object?
    }

    @Override
    public Property<?> read(JsonReader in) throws IOException {
        switch (in.peek()) {
            case NULL:
                return new SimpleObjectProperty<>(null);
            default:
                Type typeOfT = ???
                Type typeParam = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
                return ???; // how to invoke standard deserialization of my object?
        }
    }
}

有人知道怎么解决吗?

最佳答案

对于 future 的读者: 我不喜欢我最初在其他答案中实现的解决方案,因此我将其更改为使用 TypeAdapter 而不是自定义反序列化器。

这需要编写更多代码,所以我最终编写了一个轻量级库,专门用于在 JavaFX 上下文中使用 Gson,这样就没有人需要再次编写它:)

这是:FxGson .

关于java - 不为空值调用 Gson 自定义解串器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35260490/

相关文章:

java - Android:从应用程序中的多个 Activity 访问单个数据库?

java - 从 Android Studio 中的模块访问主项目?

Android 成功的 JSON 响应但 response.isSuccess() 不正确

java - 从存储过程返回的 STRUCT 中读取 ARRAY

java - 如何在Java中为gson确定运行时对象的类型

android - 使用 Retrofit Library 获取数据时如何处理 JSON 中丢失的键 android

Java序列化: 'ClassNotFoundException' when deserializing an Object

android - 在 Android 中序列化/反序列化图像的最佳方式

c# - 如何使用变量名称以 _ 或 $ 开头的对象列表反序列化 JSON 响应

java - Kafka 主题丢失消息