You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson XML无法正确反序列化Jakarta的XmlElements字段

问题:Jackson XML反序列化时@XmlElements注解字段返回null

使用Jackson XML进行Jakarta反序列化时,带有@XmlElements注解的字段始终返回null,但仅用@XmlElement的普通字段能正常解析。相关代码如下:

Java实体类代码

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "posinfo"
})
@XmlRootElement(name = "PUSH")
public class PUSH {

    @XmlElement(name = "posinfo")
    protected List<PosinfoType> posinfo;

    // 省略getter/setter等方法
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "posinfoType", propOrder = {
    "delayAndINITAndARRIVAL",
    "delimiterAndAny"
})
public class PosinfoType {

    @XmlElements({
        @XmlElement(name = "DELAY", type = DELAYType.class),
        @XmlElement(name = "INIT", type = INITType.class),
        @XmlElement(name = "ARRIVAL", type = ARRIVALType.class),
        @XmlElement(name = "ONSTOP", type = ONSTOPType.class),
        @XmlElement(name = "DEPARTURE", type = DEPARTUREType.class),
        @XmlElement(name = "ONROUTE", type = ONROUTEType.class),
        @XmlElement(name = "ONPATH", type = ONPATHType.class),
        @XmlElement(name = "OFFROUTE", type = OFFROUTEType.class),
        @XmlElement(name = "END", type = ENDType.class)
    })
    protected List<Object> delayAndINITAndARRIVAL;
    @XmlElementRef(name = "delimiter", namespace = "http://example.com/tmi8/core", type = Delimiter.class, required = false)
    @XmlAnyElement(lax = true)
    protected List<Object> delimiterAndAny;

    // 省略getter/setter等方法
 }

待解析的XML片段

<posinfo>
    <ONROUTE>
        <timestamp>2024-05-14T16:18:14+00:00</timestamp>
        <source>VEHICLE</source>
    </ONROUTE>
    <ONSTOP>
        <timestamp>2024-05-14T16:18:14+00:00</timestamp>
        <source>VEHICLE</source>
    </ONSTOP>
    <ARRIVAL>
        <timestamp>2024-05-14T16:18:16+00:00</timestamp>
        <source>VEHICLE</source>
    </ARRIVAL>
</posinfo>

Jackson配置代码(Kotlin)

object JacksonJaxbUtils {
    val objectMapperXml: ObjectMapper = XmlMapper.builder().apply {
        defaultUseWrapper(false)

        enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION)

        addModule(JakartaXmlBindAnnotationModule())

        disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
        disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        serializationInclusion(JsonInclude.Include.NON_EMPTY)
        addModule(
            JavaTimeModule().apply {
                addSerializer(XMLGregorianCalendar::class.java, XMLGregorianCalendarSerializer())
            }
        )
    }.build()

    class XMLGregorianCalendarSerializer : JsonSerializer<XMLGregorianCalendar>() {
        override fun serialize(value: XMLGregorianCalendar, generator: JsonGenerator, provider: SerializerProvider) {
            generator.writeString(value.toXMLFormat())
        }
    }
}

解决方案
  • 版本兼容性检查:确保jackson-module-jakarta-xmlbind-annotations与jackson-dataformat-xml版本完全一致,版本不匹配会导致JAXB注解无法被正确识别。
  • 显式初始化列表:Jackson不会自动初始化空列表,需在PosinfoType中为字段赋值:
    @XmlElements({
        // 注解内容不变
    })
    protected List<Object> delayAndINITAndARRIVAL = new ArrayList<>();
    
  • 调整包装器配置:全局defaultUseWrapper(false)会干扰@XmlElements字段的解析逻辑,可直接移除该配置;若必须保留,需给目标字段添加注解明确禁用包装:
    @XmlElements({
        // 注解内容不变
    })
    @JacksonXmlElementWrapper(useWrapping = false)
    protected List<Object> delayAndINITAndARRIVAL = new ArrayList<>();
    
  • 验证子类型注解:确认DELAYType、ONROUTEType等子类都正确添加了JAXB注解(如@XmlType或@XmlRootElement),否则Jackson无法完成XML元素到Java类的映射。

内容的提问来源于stack exchange,提问作者MrAndre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:41:08