为什么Jackson反序列化XML时子元素为null但属性解析正常?
问题原因
- Jackson XmlMapper默认未开启JAXB注解支持:你POJO上使用的
@XmlElement、@XmlAccessorType等均为JAXB规范注解,XmlMapper默认不识别这些配置,仅按默认字段名匹配,大小写、命名空间都无法对齐导致子元素匹配失败。 - XML携带默认命名空间:你的TripList根节点定义了
xmlns="http://hacon.de/hafas/proxy/hafas-proxy"默认命名空间,所有子节点默认归属该命名空间,POJO未配置对应命名空间映射也会触发匹配失败。
解决步骤
- 第一步:添加Jackson JAXB注解模块依赖
如果是Maven项目,在pom.xml中添加对应依赖(版本和你现有Jackson版本保持一致即可):
<dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jaxb-annotations</artifactId> <version>你的Jackson版本号</version> </dependency>
- 第二步:修改反序列化方法,注册JAXB模块
修改后的deserialize方法如下:
public <T> T deserialize(String input, Class<T> type) throws JsonProcessingException { XmlMapper mapper = XmlMapper.builder() // 注册JAXB注解支持模块,识别@XmlElement等注解 .addModule(new JaxbAnnotationModule()) // 开启XML命名空间感知 .enable(FromXmlParser.Feature.PROCESS_XML_NAMESPACES) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .build(); return mapper.readValue(input, type); }
如果只是临时验证问题不想配置命名空间,可将enable(FromXmlParser.Feature.PROCESS_XML_NAMESPACES)改为disable(FromXmlParser.Feature.PROCESS_XML_NAMESPACES),即可忽略命名空间差异直接按标签名匹配。
第三步:补全POJO命名空间配置
两种配置方式二选一即可:
方案1:单独给每个@XmlElement补充命名空间属性,同时给TripList添加@XmlRootElement注解:// 补全根节点注解 @XmlRootElement(name = "TripList", namespace = "http://hacon.de/hafas/proxy/hafas-proxy") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "TripList", propOrder = { "trip", "pricing", "sotContext" }) public class TripList extends CommonResponseType { // 给每个子元素注解补充namespace属性 @XmlElement(name = "Trip", namespace = "http://hacon.de/hafas/proxy/hafas-proxy") protected List<TripType> trip; @XmlElement(name = "Pricing", namespace = "http://hacon.de/hafas/proxy/hafas-proxy") protected List<PricingType> pricing; @XmlElement(name = "SotContext", namespace = "http://hacon.de/hafas/proxy/hafas-proxy") protected SotContextType sotContext; // 其余属性保持不变 ... }TripType类的
@XmlElement也需要补充相同的namespace属性。方案2:包级别统一配置命名空间,省去逐个添加的麻烦。在POJO所在包下创建
package-info.java文件,内容如下:@XmlSchema( namespace = "http://hacon.de/hafas/proxy/hafas-proxy", elementFormDefault = XmlNsForm.QUALIFIED ) package 你的POJO类所在包名; import javax.xml.bind.annotation.XmlNsForm; import javax.xml.bind.annotation.XmlSchema;配置后该包下所有JAXB注解的元素会默认继承该命名空间,不需要逐个添加namespace属性。
内容的提问来源于stack exchange,提问作者Chuck Nuris
相关产品推荐
相关产品推荐

