我需要为具有泛型的类编写自定义反序列化程序。我找不到办法做到这一点,但我无法想象我是唯一有这个问题的人。据我所知,有两种方法可以实现,但没有一种方法可以实现:
例如:
public class Foo<T> {}
public class FooDeserializer<T> {
public FooDeserializer(Class<T> type) { ... }
...
}
// Boilerplate code...
module.addDeserializer(Foo.class, new FooDeserializer<Bar1>(Bar1.class));
module.addDeserializer(Foo.class, new FooDeserializer<Bar2>(Bar2.class));
这不起作用,当ObjectMapper实例获取Foo的实例时,没有可用的泛型参数的类型信息(类型擦除),因此它只选择最后一个反序列化器注册。
例如:
String json = "...";
ObjectMapper mapper = ...;
Foo<Bar1> foo = new Foo<>(Bar1.class);
foo = mapper.readValue(json, Foo.class); // Can't pass empty foo instance with Class<?> field containing Bar1.class
需要这样的东西:
mapper.readValue(json, Foo.class, Bar1.class); // Doesn't exist in jackson
有任何建议怎么做?
编辑: 我找到了解决问题的方法,但它并不是一个干净的解决方案:
我使用Class字段扩展FooDeserializer以保存Foo的通用参数的类型。然后,每次我想将一些json反序列化为一个新的Foo实例时,我得到一个新的ObjectMapper实例(我在工厂的预配置实例上使用ObjectMapper #copy)并传递一个新的Module,其中包含一个FooDeserializer的实例。 class参数(我知道此时的类型)。 Module,FooDeserializer和ObjectMapper副本都是短命的,它们只是为这个单一的反序列化操作实例化。正如我所说,不是很干净,但仍然比多次子类化Foo并为每个编写反序列化器更好。
示例:
public class FooDeserializer<T> extends StdDeserializer<T> {
private Class<T> type;
public FooDeserializer(Class<T> type) { this.type = type }
...
}
// Meanwhile, before deserialization:
ObjectMapper mapper = MyObjectMapperFactory.get().copy();
SimpleModule module = new SimpleModule(new Version(0,0,1,null,null,null);
module.addDeserializer(Foo.class, new FooDeserializer(Bar1.class);
mapper.addModule(module);
Foo<Bar1> x = mapper.readValue(json, Foo.class);
可能将其用于隐藏丑陋的实用方法。
答案 0 :(得分:0)
我认为你不需要编写我们自己的自定义反序列化器。您可以使用此语法反序列化使用泛型的对象,这些对象取自另一个Stack Overflow线程。
mapper.readValue(jsonString, new TypeReference<Data<String>>() {});
情侣来源帮助您: Jackson - Deserialize using generic class http://www.tutorialspoint.com/jackson/jackson_data_binding_generics.htm
答案 1 :(得分:0)
您不需要编写自定义反序列化程序。通过将Jackson注释放在作为参数传递给泛型类的类型上,可以对泛型进行反序列化
注释类Bar1
如下:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("Bar1")
class Bar1 {
}
现在,当您反序列化Foo<Bar1>
的实例时,Jackson会将类型参数信息放入JSON中。然后可以将此JSON反序列化为泛型类Foo.class
,就像反序列化任何其他类一样。
ObjectMapper mapper = ...;
Foo<Bar1> foo = new Foo<Bar1>();
String json = objectMapper.writeValueAsString(foo);
foo = mapper.readValue(json, Foo.class); // no need to specify the type Bar1.
因此,如果每个可以作为参数传递给Foo的类都有注释,那么可以在编译时不知道类型参数的情况下反序列化JSON。
请参阅Polymorphic Deserialization和Annotations上的杰克逊文档。