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

Java Jackson XML泛型反序列化异常问题排查

问题原因:Java泛型类型擦除

你遇到的问题核心是Java泛型的类型擦除机制:

  • 编译后,MyXmlManager<T>中的泛型参数T会被擦除为Object,所以你在方法中创建的new TypeReference<XmlGeneric<T>>() {},在运行时实际代表的是XmlGeneric<Object>类型。
  • Jackson无法获取到T的实际类型(比如Person),只能将XML节点默认反序列化为LinkedHashMap来存储键值对,这就是为什么你看到{name=charles, userid=1}这种输出,强制转换时会抛出ClassCastException。

而直接使用new TypeReference<XmlGeneric<Person>>() {}时,编译器会把Person这个具体类型保留在匿名内部类的类型元数据中(TypeReference正是利用匿名内部类能保留泛型类型信息的特性工作),所以Jackson能正确识别目标类型,完成反序列化。

解决方案

下面提供两种可行的修复方式,核心都是在运行时为Jackson提供明确的泛型类型信息:

方法1:在反序列化方法中传入目标类型信息

修改MyXmlManager,让方法接收Class<T>或者TypeReference,直接传递给Jackson:

方式1.1 传入Class<T>构造JavaType

public class MyXmlManager {
    final static XmlMapper oXmlMapper = new XmlMapper();
    
    public <T> XmlGeneric<T> xmlDeserialization(String sXmlData, Class<T> elementType) throws JsonProcessingException {
        // 构造XmlGeneric<T>的JavaType
        JavaType targetType = oXmlMapper.getTypeFactory()
                .constructParametricType(XmlGeneric.class, elementType);
        return oXmlMapper.readValue(sXmlData, targetType);
    }
}

调用代码:

MyXmlManager myXmlManager = new MyXmlManager();
XmlGeneric<Person> xmlPerson = myXmlManager.xmlDeserialization(xmlPersonData, Person.class);
System.out.println(xmlPerson);
// 输出:XmlGeneric [rows=[person [name=charles, userid=1], person [name=arthur, userid=2]]]

方式1.2 直接传入TypeReference

public class MyXmlManager {
    final static XmlMapper oXmlMapper = new XmlMapper();
    
    public <T> XmlGeneric<T> xmlDeserialization(String sXmlData, TypeReference<XmlGeneric<T>> typeRef) throws JsonProcessingException {
        return oXmlMapper.readValue(sXmlData, typeRef);
    }
}

调用代码:

MyXmlManager myXmlManager = new MyXmlManager();
XmlGeneric<Person> xmlPerson = myXmlManager.xmlDeserialization(xmlPersonData, 
        new TypeReference<XmlGeneric<Person>>() {});

方法2:在MyXmlManager实例化时保存类型信息

如果希望MyXmlManager实例绑定固定的泛型类型,可以在构造时传入类型信息并保存:

public class MyXmlManager<T> {
    final static XmlMapper oXmlMapper = new XmlMapper();
    private final JavaType targetType;
    
    public MyXmlManager(Class<T> elementType) {
        this.targetType = oXmlMapper.getTypeFactory()
                .constructParametricType(XmlGeneric.class, elementType);
    }
    
    public XmlGeneric<T> xmlDeserialization(String sXmlData) throws JsonProcessingException {
        return oXmlMapper.readValue(sXmlData, targetType);
    }
}

调用代码:

MyXmlManager<Person> myXmlManager = new MyXmlManager<>(Person.class);
XmlGeneric<Person> xmlPerson = myXmlManager.xmlDeserialization(xmlPersonData);

以上两种方法都能让Jackson在运行时获取到T的实际类型,从而正确将<row>节点反序列化为对应的POJO对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:37:08