首页 > 解决方案 > 使用 JAXB 以确定的顺序生成子元素

问题描述

我有一个大致如下形状的类:

@XmlRootElement("foo")
public class Foo {
    @XmlElement
    public Integer b;

    @XmlElement
    public Integer a;
}

我现在注意到 JAXB 显然指定它是未定义的(并且取决于 JVM 反射实现的细节),无论 aFoo被序列化为<foo><a>123</a><b>456</b></foo>还是<foo><b>456</b><a>123</a></foo>. 这使得在每次都应该产生相同结果的自动测试中比较输出变得很困难。

我试过添加

@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)

到班级。起初这似乎工作正常,但现在解组器拒绝解析没有此注释的旧代码编写的数据。

有没有办法让 JAXB 以确定的顺序输出子元素但在其输入中接受任何顺序?


编辑:这实际上可能不是 JAXB 问题,而是底层 XML 解析器之一比它应该更挑剔。我得到的潜在异常是

org.xml.sax.SAXParseException; lineNumber: 59; columnNumber: 16; cvc-complex-type.2.4.d: Invalid content was found starting with element 'a'. No child element is expected at this point.

标签: javajaxbsaxparser

解决方案


@XmlType您可以使用和定义订单,propOrder如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement("foo")
@XmlType(name = "", propOrder = {
    "a",
    "b"
})
public class Foo {
    @XmlElement
    public Integer b;

    @XmlElement
    public Integer a;
}

编辑

这是我的 JAXB 配置:

    //Prepare JAXB objects
    JAXBContext jc = JAXBContext.newInstance(Foo.class);
    Unmarshaller u = jc.createUnmarshaller();

    //Create an XMLReader to use with our filter
    XMLReader reader = XMLReaderFactory.createXMLReader();

    //Prepare the input, in this case a java.io.File (output)
    InputStream stream = new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8));
    Reader isr = new InputStreamReader(stream, "UTF-8");
    InputSource is = new InputSource(isr);

    //Create a SAXSource specifying the filter
    SAXSource source = new SAXSource(is);

    //Do unmarshalling
    ret = (Foo) u.unmarshal(source);

推荐阅读