【问题标题】:Gson - JsonSerializer in TypeAdapterFactory or generic type in TypeAdapterGson - TypeAdapterFactory 中的 JsonSerializer 或 TypeAdapter 中的泛型类型
【发布时间】:2016-04-19 17:51:38
【问题描述】:

我正在尝试为我正在使用的 JavaFX 类型(不同的属性和可观察对象)编写 TypeAdapterFactory。对于ObjectProperty,我可以编写一个JsonSerializer/Deserializer,利用ParamterizedType 的转换,然后得到ActualTypeArguments。

这是我用来实现此目的的代码:

public class ObjectPropertySerializer implements JsonSerializer<ObjectProperty>, JsonDeserializer<ObjectProperty> {

    @Override
    public ObjectProperty deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Type objectType = ((ParameterizedType)typeOfT).getActualTypeArguments()[0];
        return new SimpleObjectProperty(new GsonBuilder().create().fromJson(json, objectType));
    }

    @Override
    public JsonElement serialize(ObjectProperty src, Type typeOfSrc, JsonSerializationContext context) {
        Type objectType = ((ParameterizedType)typeOfSrc).getActualTypeArguments()[0];
        return new GsonBuilder().create().toJsonTree(src.getValue(), objectType);
    }
}

但是,由于嵌套类/对象和直接序列化,我还需要使用 TypeAdapterFactory,这在使用 .registerTypeAdapter() 将序列化程序直接注册到 GsonBuilder 时不起作用。

这是到目前为止我工厂的代码(其他属性已经工作):

public class JFXGsonAdapterFactory implements TypeAdapterFactory {

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if ( BooleanProperty.class.isAssignableFrom(type.getRawType()) ) {
            return (TypeAdapter<T>) new BooleanPropertyAdapter();
        }
        else if ( DoubleProperty.class.isAssignableFrom(type.getRawType()) ) {
            return (TypeAdapter<T>) new DoublePropertyAdapter();
        }
        else if (IntegerProperty.class.isAssignableFrom(type.getRawType()) ) {
            return (TypeAdapter<T>) new IntegerPropertyAdapter();
        }
        else if (ObjectProperty.class.isAssignableFrom(type.getRawType()) ) {
            return (TypeAdapter<T>) new ObjectPropertyAdapter(gson);
        }
        else if ( StringProperty.class.isAssignableFrom(type.getRawType()) ) {
            return (TypeAdapter<T>) new StringPropertyAdapter();
        }
        else {
            return null;
        }
    }
}

我无法在此处返回序列化器/反序列化器接口的实现,但需要使用扩展 TypeAdapter 的适配器类。

这是我对ObjectProperty 的TypeAdapter 实现:

public class ObjectPropertyAdapter<T> extends TypeAdapter<ObjectProperty> {

    private Gson gson;
    TypeAdapter<JsonElement> elementAdapter;

    public ObjectPropertyAdapter( Gson gson ) {
        this.gson = gson;
        elementAdapter = gson.getAdapter(JsonElement.class);
    }

    @Override
    public void write(JsonWriter out, ObjectProperty value) throws IOException {
        if ( value == null ) {
            out.nullValue();
        } else {
            JsonElement jsonElement = gson.toJsonTree(value.get());
            elementAdapter.write(out, jsonElement);
        }
    }

    @Override
    public ObjectProperty read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        } else {
            // Read
            return null; // tmp
        }
    }

}

但是我不确定如何在 TypeAdapter 中获取 ObjectProperty 的泛型类型,我也不知道如何从 TypeToken 中获取它(因为我可以将它从工厂传递给适配器)。


问题总结:

1) 如何将 JsonSerializer/Deserializer 的实现转换为 TypeAdapter

或

2) 我怎样才能获得通用类型,例如来自 TypeToken 的 ObjectProperty?

或

3) 我需要做一些完全不同的事情来实现这一目标吗?

【问题讨论】:

    标签: java javafx gson


    【解决方案1】:

    1) 你不能。 JsonSerializer 和 JsonDeserializer 是 old 转换器方式。新应用程序应使用 TypeAdapter,它具有超集的功能。

    2) 假设您的意思是 JavaFX 的 ObjectProperty&lt;T&gt; 并且您想要提取 T 的类。

    您可以使用TypeToken#getType() 轻松访问TypeToken 内的Type。

    我将使用List&lt;String&gt; 给出示例,这是相同的想法,但易于测试。

    TypeToken<List<String>> typeToken = new TypeToken<List<String>>(){};
    
    System.out.println("typeToken.getRawType() = " + typeToken.getRawType());
    Type type = typeToken.getType();
    System.out.println("typeToken.getType() = " + type);
    if (type instanceof ParameterizedType) {
      Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
      System.out.println("typeArguments = " + Arrays.toString(typeArguments));
    }
    

    输出结果:

    typeToken.getRawType() = interface java.util.List
    typeToken.getType() = java.util.List<java.lang.String>
    typeArguments = [class java.lang.String]
    

    3) 我想你快到了。 ;-) 啊,使用 TypeAdapter,您不会考虑 JsonObject 或 JsonElement(DOM 样式),而是动态构建对象或 JSON 表示(流样式)。

    另外,在你的问题中你说

    但是由于嵌套,我还需要使用 TypeAdapterFactory 类/对象和直接序列化,当 使用直接将序列化程序注册到 GsonBuilder .registerTypeAdapter()。

    也许您需要使用GsonBuilder#registerTypeHierarchyAdapter() 并查找那些嵌套类。这将取决于您的问题详情。

    【讨论】:

    • 不幸的是,typeToken.getType 似乎不是 ParameterizedType 的实例:/
    • 它是什么类型的?可以调试吗?您可以从 TypeToken 中获得哪些信息?我还添加了关于 GsonBuilder#registerTypeHierarchyAdapter() 的另一条评论。
    • java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    • 好的,我需要使用:TypeToken&lt;SimpleObjectProperty&lt;CustomClass&gt;&gt; typeToken = new TypeToken&lt;SimpleObjectProperty&lt;CustomClass&gt;&gt;(){}; 而不仅仅是 ObjectProperty,因为那只是一个抽象类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多