我正在尝试为我正在使用的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,当使用GsonBuilder将序列化程序直接注册到.registerTypeAdapter()时,这些方法不起作用。

这是到目前为止我工厂的代码(其他属性已经起作用):
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的适配器类。

这是我的TypeAdapterObjectProperty实现:
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)我需要做一些完全不同的事情来实现这一目标吗?

最佳答案

1)你不能。 JsonSerializerJsonDeserializer是旧的转换方式。新应用程序应使用TypeAdapter,它具有功能上的超集。

2)假设您的意思是JavaFX的 ObjectProperty<T> ,并且要提取T的类。

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

我将使用List<String>给出示例,该示例是相同的想法,但易于测试。

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,您不会以JsonObjectJsonElement(DOM样式)来考虑,而是在运行时(流样式)构建对象或JSON表示形式。

另外,在您的问题中,您说

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

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

10-05 19:12