升级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。
需要做两处修改:
修正
Response类中data字段的命名空间为完整URI
将@XmlElement的namespace值从前缀rs替换为XML中定义的完整命名空间urn:schemas-microsoft-com:rowset。为
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
相关产品推荐
相关产品推荐

