我尝试使用相同的JAXB注释绑定XML和JSON(使用JaxbAnnotationModule)。
XML <--> JAXB <--> Jackson <--> JSON
我必须使用JAXB注释,不能改变它们。我的问题是某些XML直接转换为泛型类JAXBElement<T>
而不是类T
。这导致了JSON输出:
{
"JAXBElement":{
"name":"{http://www.opengis.net/wps/1.0.0}Capabilities",
"declaredType":"net.opengis.wps.v_1_0_0.WPSCapabilitiesType",
"scope":"javax.xml.bind.JAXBElement$GlobalScope",
"value":{
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
},
"nil":false,
"globalScope":true,
"typeSubstituted":false
}
}
虽然我想要:
{
"Capabilities":{
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
}
}
类型T
的真实对象由JAXBElement包装。对于某些根元素可能会发生这种情况,并且嵌套在对象树中的任何位置。如果我打电话给getValue()
,我就会得到真实的对象。但是当JAXBElement<T>
不是根元素时,我无法做到这一点,因为Jackson是JAXB和JSON之间唯一的解释器,我既不能改变JAXB-Binding也不能改变创建的对象(其他的一些部分)代码也使用它们。)
所以我发现可以解决问题的是MixIns:
// a mixin annotation that overrides the handling for the JAXBElement
public static interface JAXBElementMixin<T> {
@JsonValue
Object getValue();
}
ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.addMixInAnnotations(JAXBElement.class, JAXBElementMixin.class);
这解决了其他元素的问题,但导致对象的名称为JAXBElement
而不是T
(在我的情况下为Capabilities
):
{
"JAXBElement":{ // <------ Should be 'Capabilities' because of type JAXBElement<Capabilities>
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
}
}
问题:
任何想法我可以做什么(可能注释JAXBElementMixin<T>
)以获得正确的类型Capabilities
作为对象名称(还有其他类而不是Capabilities
可以放置为{{ 1}},也是)?
还有其他想法如何跳过对象树中任何位置的任何T
的序列化,并继续对其JAXBElement<T>
方法后面的对象进行序列化?
答案 0 :(得分:0)
这不是您问题的直接答案,但可能是实现目标的方法。
如果您只想摆脱最顶层的JAXBElement
,为什么不定制XJC为Capabilities
元素生成额外的课程?
类似的东西:
<jaxb:bindings node="xs:element[@name='Capabilities']">
<jaxb:class name="Capabilities"/>
</jaxb:bindings>
这应该生成一个用&#39; @ XmlRootElement&#39;注释的类Capabilities
。因此,您将摆脱JAXBElement
。
答案 1 :(得分:0)
杰克逊不支持JAXBElement
,因为它非常特定于XML并且难以与其他格式一起使用:杰克逊JAXB支持专注于使用注释中的信息来使事情有效,但目标不是成为一个完整的JAXB实现。
因此,最好的办法是做@lexicore建议并尝试避免使用JAXBElement
。