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

如何使用泛型对XML元素列表进行反序列化?

如何用泛型反序列化XML元素列表?

我尝试用泛型方法反序列化XML中的元素列表,但代码运行失败,相关代码和错误信息如下:

XML内容:

String xml = "<cats><cat><name>Ms. Piggy</name><city>Londen</city></cat><cat><name>Ms. Jerry</name><city>Londen</city></cat></cats>";

Processor pr = new Processor();
List<CatXML> cats = pr.xmlToObjectList(xml, CatXML.class);

Processor类代码:

public class Processor {
    public <T> List<T> xmlToObjectList(String xmlContainsObject, Class<T> objectType) {
        try {
            JAXBContext context = JAXBContext.newInstance(objectType);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            StringReader reader = new StringReader(xmlContainsObject);
            return (List<T>) unmarshaller.unmarshal(reader);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

CatXML类代码:

@XmlRootElement(name = "cat")
@XmlAccessorType(XmlAccessType.FIELD)
public class CatXML implements Serializable {
    private String name = "";
    private String city = "";

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
}

运行后抛出错误:

Exception in thread "main" java.lang.RuntimeException: jakarta.xml.bind.UnmarshalException: unexpected element (uri:"", local:"cats"). Expected elements are <{}cat>
at org.example.Processor.xmlToObjectList(Processor.java:90)
at org.example.Main.main(Main.java:36)
Caused by: jakarta.xml.bind.UnmarshalException: unexpected element (uri:"", local:"cats"). Expected elements are <{}cat>
at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:701)

解决方案

错误原因

你的XML根元素是<cats>,但JAXB上下文只注册了CatXML类(对应<cat>元素),反序列化时JAXB找不到匹配<cats>的类,因此抛出异常。JAXB无法直接将根元素为集合容器的XML反序列化为List,需要一个包装类来对应根元素。

方法一:创建根元素包装类

  1. 新增CatsXML类,对应<cats>根元素,内部包含List<CatXML>:
@XmlRootElement(name = "cats")
@XmlAccessorType(XmlAccessType.FIELD)
public class CatsXML implements Serializable {
    @XmlElement(name = "cat")
    private List<CatXML> cats;

    public List<CatXML> getCats() { return cats; }
    public void setCats(List<CatXML> cats) { this.cats = cats; }
}
  1. 修改调用逻辑,先反序列化为CatsXML,再取出列表:
Processor pr = new Processor();
CatsXML catsWrapper = pr.xmlToObject(xml, CatsXML.class);
List<CatXML> cats = catsWrapper.getCats();

同时可以修改Processor类,添加通用的单对象反序列化方法:

public class Processor {
    public <T> T xmlToObject(String xml, Class<T> objectType) {
        try {
            JAXBContext context = JAXBContext.newInstance(objectType);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            StringReader reader = new StringReader(xml);
            return objectType.cast(unmarshaller.unmarshal(reader));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

方法二:不创建包装类,直接处理XML流

如果不想新增包装类,可以用XMLStreamReader定位到<cat>元素,逐个反序列化:

public <T> List<T> xmlToObjectList(String xml, Class<T> objectType) {
    try {
        JAXBContext context = JAXBContext.newInstance(objectType);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));

        // 跳过根元素<cats>,定位到<cat>元素
        while (reader.hasNext()) {
            if (reader.isStartElement() && reader.getLocalName().equals(objectType.getAnnotation(XmlRootElement.class).name())) {
                break;
            }
            reader.next();
        }

        List<T> result = new ArrayList<>();
        while (reader.isStartElement() && reader.getLocalName().equals(objectType.getAnnotation(XmlRootElement.class).name())) {
            T obj = unmarshaller.unmarshal(reader, objectType).getValue();
            result.add(obj);
            // 移动到下一个元素
            reader.next();
        }
        return result;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

这种方法不需要修改现有类,直接通过XML流遍历目标元素完成反序列化。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:24:52