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

升级Java 17与SpringBoot后JAXB反序列化失效,如何适配新库?

问题:JAXB升级到GlassFish版本后XML反序列化失败

升级到Java 17并将JAXB库从com.sun.xml.bind/jaxb-impl/2.2.11-xsd-doc-0.2.0替换为org.glassfish.jaxb/jaxb-runtime/2.3.7后,原XML反序列化逻辑出现异常:解析后的Response对象中data字段为null,而旧版本能正常解析出Data(row=[Row(error=0)])。

原代码与输入XML

Kotlin实体类与反序列化方法

import java.io.StringReader
import javax.xml.bind.JAXBContext
import javax.xml.bind.Unmarshaller
import javax.xml.bind.annotation.*

val jaxbContext: JAXBContext = JAXBContext.newInstance(Response::class.java)
val jaxbUnmarshaller: Unmarshaller = jaxbContext.createUnmarshaller()

@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
data class Response(@XmlElement(name = "data", namespace = "rs") val data: Data? = null)
data class Data(@field:XmlElement(name = "Row") val row: MutableList<Row>? = null)
data class Row(@XmlAttribute val error: String? = null)

fun umarshallAsSimpleResponse(xmlString: String): Response {
    val reader = StringReader(xmlString)
    return jaxbUnmarshaller.unmarshal(reader) as Response
}

输入XML

<xml xmlns:s='uuid:BDC6E3FO-6DA3-1ldl-A2A3-00AA00C14882' 
     xmlns:dt='uuid:C2F41010-6583-1ldl-429F-OOAAOOC14882'
     xmlns:rs='urn:schemas-microsoft-com:rowset' 
     xmlns:z='#Rowsetschema'>
    <rs:data>
        <Row error="0" Usl=" " Data=" " Przedz=" " Cena=" " Ilosc="0" Konto=" "
             errorMessage="Status został zmieniony."></Row>
    </rs:data>
</xml>

解决方案

问题根源在于新旧JAXB实现对命名空间的处理严格程度不同:旧版Sun JAXB允许使用命名空间前缀(如rs)代替完整URI,而GlassFish JAXB严格遵循规范,要求使用实际的命名空间URI。

需要做两处修改:

  1. 修正Response类中data字段的命名空间为完整URI
    将@XmlElement的namespace值从前缀rs替换为XML中定义的完整命名空间urn:schemas-microsoft-com:rowset。

  2. 为Data类添加@XmlAccessorType注解
    保持与Response类一致的属性访问策略,避免Kotlin data类的属性访问逻辑被JAXB误解。

修改后的代码

import java.io.StringReader
import javax.xml.bind.JAXBContext
import javax.xml.bind.Unmarshaller
import javax.xml.bind.annotation.*

val jaxbContext: JAXBContext = JAXBContext.newInstance(Response::class.java)
val jaxbUnmarshaller: Unmarshaller = jaxbContext.createUnmarshaller()

@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
data class Response(
    @XmlElement(name = "data", namespace = "urn:schemas-microsoft-com:rowset") 
    val data: Data? = null
)

@XmlAccessorType(XmlAccessType.FIELD)
data class Data(@field:XmlElement(name = "Row") val row: MutableList<Row>? = null)

data class Row(@XmlAttribute val error: String? = null)

fun umarshallAsSimpleResponse(xmlString: String): Response {
    val reader = StringReader(xmlString)
    return jaxbUnmarshaller.unmarshal(reader) as Response
}

验证结果

修改后重新解析XML,将得到与旧版本一致的结果:

Response(data=Data(row=[Row(error=0)]))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:25:37