英文:
How to set up a collection of abstract classes with JAXB for deserializetion in Jackson?
问题
我有一个实体结构,在树的根节点下已经有一个类(PoFoconNetz
),它包含一个 Set
字段,其中包含一个 抽象 类(PoFoconKnoten
)的实例,该抽象类有三种可能的实现(PoBAC32
、PoBAC12
和 PoBAU
)。
以下是应用于这些类的来自 javax.xml.bind.annotation.*
包的注释:
- 对于
PoFoconNetz
:@XmlSeeAlso({ PoBAC32.class, PoBAC12.class, PoBAU.class })
- 对于
PoFoconNetz
中的Set<PoFoconKnoten>
字段,称为foconKnoten
:
@XmlElementWrapper(name = "foconKnoten")
@XmlElements(value = {
@XmlElement(name = "PoBAC32", type = PoBAC32.class),
@XmlElement(name = "PoBAC12", type = PoBAC12.class),
@XmlElement(name = "PoBAU", type = PoBAU.class) })
- 对于抽象类
PoFoconKnoten
:@XmlSeeAlso({ PoBAC32.class, PoBAC12.class, PoBAU.class })
- 对于三个具体子类:
@XmlRootElement
在发送端,这些类通过 JAXB(2.3.0)序列化为 XML,以便发送到 REST 终端点,结果为以下 XML 结构:
<[...省略根项目...]>
<foconNetz [...属性...]>
<foconKnoten>
<PoBAC12 [...属性...]>
<[...进一步的子项目...]>
</PoBAC12>
</foconKnoten>
</foconNetz>
接收方的 Spring 应用程序然后使用 Jackson 2.9.9 来还原原始的 Java 实体。下面的部分可能与此相关,因为这些部分应该使得处理 JAXB 注解成为可能:
@Autowired
private ObjectMapper jacksonObjectMapper;
[...]
jacksonObjectMapper.registerModule(new JaxbAnnotationModule());
jacksonObjectMapper.setAnnotationIntrospector(new
XmlJaxbAnnotationIntrospector(jacksonObjectMapper.getTypeFactory()));
但是当发送的 XML 到达接收方时,Jackson 报错,指出无法实例化 PoFoconKnoten
,似乎对 XML 中包含的类型信息视而不见:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `my.company.product.PoFoconKnoten` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 252] (through reference chain: [...各种其他类...]->my.company.product.PoFoconNetz["foconKnoten"]->java.util.HashSet[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.9.jar:2.9.9]
英文:
I have an entity structure, where one class, already a few levels down from the root of the tree, (PoFoconNetz
) has a Set
field, containing instances of an abstract class (PoFoconKnoten
) with three possible implementations (PoBAC32
, PoBAC12
and PoBAU
).
The following annotations from the javax.xml.bind.annotation.*
package are applied to the classes:
- To
PoFoconNetz
:@XmlSeeAlso({ PoBAC32.class, PoBAC12.class, PoBAU.class })
- To the
Set<PoFoconKnoten>
field inPoFoconNetz
, calledfoconKnoten
:
@XmlElementWrapper(name = "foconKnoten")
@XmlElements(value = {
@XmlElement(name = "PoBAC32", type = PoBAC32.class),
@XmlElement(name = "PoBAC12", type = PoBAC12.class),
@XmlElement(name = "PoBAU", type = PoBAU.class) })
- To the abstract
PoFoconKnoten
class:@XmlSeeAlso({ PoBAC32.class, PoBAC12.class, PoBAU.class })
- To the three concrete subclasses:
@XmlRootElement
On the sender side, these classes are serialized into XML using JAXB (2.3.0), in order to be sent to a REST endpoint, resulting in an XML like this:
<[...ROOT ITEMS OMITTED...]>
<foconNetz [...ATTRIBUTES...]>
<foconKnoten>
<PoBAC12 [...ATTRIBUTES...]>
<[...FURTHER SUB-ITEMS...]>
</PoBAC12>
</foconKnoten>
</foconNetz>
Then, the receiver Spring application uses Jackson 2.9.9 to restore the original Java entities. Here the following parts could be relevant, as these are supposed to enable the processing of JAXB annotations:
@Autowired
private ObjectMapper jacksonObjectMapper;
[...]
jacksonObjectMapper.registerModule(new JaxbAnnotationModule());
jacksonObjectMapper.setAnnotationIntrospector(new
XmlJaxbAnnotationIntrospector(jacksonObjectMapper.getTypeFactory()));
But when the sent XML arrives on the receiver side, Jackson throws an error, complaining about the non-ability to instantiate a PoFoconKnoten
, seemingly oblivious to the type information contained in the XML:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `my.company.product.PoFoconKnoten` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 252] (through reference chain: [...VARIOUS OTHER CLASSES...]->my.company.product.PoFoconNetz["foconKnoten"]->java.util.HashSet[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.9.jar:2.9.9]
I'd love to receive any pointers about what could be the cause of the problem and how could I go about solving it.
专注分享java语言的经验与见解,让所有开发者获益!
评论