我想为Class Literals设置一个Serializer和Deserializer。它应该从/到JSON字符串映射。它也应该适用于泛型类。
我尝试编写自定义反序列化程序,但它处理所有类,而不仅仅是我想要的类:
Mutex
杰克逊将为每个public class MyDeserializer extends JsonDeserializer<Class<? extends Foo>> {
public Class<? extends Foo> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String token = jp.getText();
switch(token) {
case "FOO": return Foo.class;
case "BAR": return Bar.class;
}
return null;
}
}
打电话给这个解串器。但我只是希望它被Class<?>
调用。
顺便说一句:我想将此注册为全局解串器。我不想要在任何地方使用Class<? extends Foo>
。
我怎样才能使其正常工作?
提前致谢。
POJO:
@JsonDeserialize
JSON:
public class MyPOJO {
public Class<? extends Foo> fooType;
}
ObjectMapper用法:
{
"fooType": "FOO"
}
答案 0 :(得分:0)
由于Type Erasure,您尝试实现的目标似乎是不可能的,实际上在运行时,您的班级MyDeserializer
被视为JsonDeserializer<Class>
而您的字段fooType
只是键入Class
而不是类型Class<? extends Foo>
,这实际上是为每个Class<?>
调用反序列化器的原因。
在您的情况下,最佳解决方案是使用Class<? extends Foo>
为@JsonDeserialize(using = MyDeserializer.class)
类型的字段添加注释,以便在运行时指示要使用的反序列化程序,但是您不想这样做,作为解决方法,假设在给定的类中,当你有类型Class
的字段时,它们都将使用相同的反序列化器(自定义或默认),你可以简单地修改你的类MyDeserializer
以首先检查当前的bean类,以了解我们是否应该使用自定义反序列化器或默认反序列化器。
您可以将其注册为下一个:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("MyModule")
.addDeserializer(Class.class, new MyDeserializer());
mapper.registerModule(module);
您的反序列化程序的代码将是:
public class MyDeserializer extends JsonDeserializer<Class<?>> {
// The default deserializer for a property of type Class
private final FromStringDeserializer.Std defaultDeserializer;
public MyDeserializer() {
// Set the default deserializer
this.defaultDeserializer = FromStringDeserializer.findDeserializer(Class.class);
}
public Class<?> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
// Check whether we should used the custom or default deserializer
// based on the bean class
if (accept(jp.getCurrentValue().getClass())) {
// The custom deserializer
String token = jp.getText();
switch(token) {
case "FOO": return Foo.class;
case "BAR": return Bar.class;
}
return null;
}
// Call the default deserializer
return (Class<?>) defaultDeserializer.deserialize(jp, ctxt);
}
// Returns true if this bean class has fields of type Class that must
// be deserialized with the custom deserializer, false otherwise
public boolean accept(Class<?> beanClass) {
// Implement your logic here
// You could for example have all the bean classes in a Set and
// check that the provided class is in the Set
}
}