jackson解串器为通用类型

我需要为具有generics的类编写自定义反序列化器。 我找不到办法做到这一点,但我无法想象我是唯一有这个问题的人。 据我所知,有两种方法可以实现它,但它们都不是可实现的:

  1. 在反序列化器的构造函数中为反序列化器提供Class参数不起作用,因为在注册反序列化器时,Type.class与反序列化器实例之间的关系将丢失。

例如:

public class Foo {} public class FooDeserializer { public FooDeserializer(Class type) { ... } ... } // Boilerplate code... module.addDeserializer(Foo.class, new FooDeserializer(Bar1.class)); module.addDeserializer(Foo.class, new FooDeserializer(Bar2.class)); 

这不起作用,当ObjectMapper实例获取Foo的实例时,没有可用的generics参数的类型信息(类型擦除),因此它只选择最后注册的反序列化器。

  1. 在类中保留generics类型的引用没有帮助,因为类的实例化版本无法传递给反序列化器(接口是readValue(String,Class))。

例如:

 String json = "..."; ObjectMapper mapper = ...; Foo 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的generics参数的类型。 然后,每次我想将一些json反序列化为一个新的Foo实例时,我得到一个新的ObjectMapper实例(我在工厂的预配置实例上使用ObjectMapper #copy)并传递一个新的Module,其中包含一个FooDeserializer的实例。 class参数(我知道此时的类型)。 Module,FooDeserializer和ObjectMapper副本都很短,它们只是为这个单一的反序列化操作实例化。 正如我所说,不是很干净,但仍然比多次子类化Foo并为每个编写反序列化器更好。

例:

 public class FooDeserializer extends StdDeserializer { private Class type; public FooDeserializer(Class 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 x = mapper.readValue(json, Foo.class); 

可能会把它变成一种实用的方法来隐藏丑陋。

我认为你不需要编写我们自己的自定义反序列化器。 您可以使用此语法反序列化使用generics的对象,这些对象取自另一个Stack Overflow线程。

 mapper.readValue(jsonString, new TypeReference>() {}); 

几个来源帮助你: Jackson – 使用generics类反序列化 http://www.tutorialspoint.com/jackson/jackson_data_binding_generics.htm

您不需要编写自定义反序列化程序。 可以通过将Jackson注释放在作为参数传递给generics类的类型上来反序列化generics。
注释类Bar1如下:

 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonTypeName("Bar1") class Bar1 { } 

现在,当您反序列化Foo的实例时,Jackson会将类型参数信息放入JSON中。 然后可以将此JSON反序列化为generics类Foo.class就像反序列化任何其他类一样。

 ObjectMapper mapper = ...; Foo foo = new Foo(); String json = objectMapper.writeValueAsString(foo); foo = mapper.readValue(json, Foo.class); // no need to specify the type Bar1. 

因此,如果每个可以作为参数传递给Foo的类都有注释,那么可以在编译时不知道类型参数的情况下反序列化JSON。

请参阅Jackson关于多态反序列化和注释的文档。