Object的JaxB表示支持不同类型

时间:2018-03-07 02:30:15

标签: jaxb

以下java属性可以是String / Integer类型。我尝试添加注释,如下所示,但它只采用最后一种类型(在这种情况下为字符串),即使传递整数。我们如何为这个属性允许多种类型?

@XmlElements({
@XmlElement(type = Integer.class), @XmlElement(type = String.class)
})
private Object val1;

1 个答案:

答案 0 :(得分:2)

问题是在解组时没有名称来区分不同类型的类。我不知道你的要求到底是什么,但这就是你如何使它发挥作用:

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class SomeRoot {
    @XmlElements({
            @XmlElement(name="string", type = String .class),
            @XmlElement(name="int", type = Integer.class)
    })
    private Object val;

    public SomeRoot(Object val) {
        this.val = val;
    }

    public SomeRoot() { }
}

当你提供了一个字符串值时,它将被编组成类似的东西:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <string>test</string>
</root>

当给出一个整数时,它会编组成类似的东西:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <int>1</int>
</root>

由于元素名称的不同,这两种方法都会被解组为正确的类型。

此外,如果你有一个对象列表,你可以编组/解组这样的东西没有问题:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <int>1</int>
    <string>test1</string>
    <string>test2</string>
    <string>test3</string>
    <int>3</int>
</root>

更新

如果您想在<val>元素下使用这两种类型,则可以使用自定义XmlAdapter来检查类型。这看起来像这样:

public class MyXmlAdapter extends XmlAdapter<Object, Object> {

    private DocumentBuilder documentBuilder;

    public MyXmlAdapter() {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            documentBuilder = dbf.newDocumentBuilder();
        } catch(Exception e) {
            // TODO - Handle Exception
        }
    }

    @Override
    public Object unmarshal(Object v) throws Exception {
        Element element = (Element) v;
        String elementValue = element.getTextContent();
        if(StringUtils.isNumeric(elementValue)) {
            return Integer.parseInt(elementValue);
        } else {
            return new String(elementValue);
        }
    }

    @Override
    public Object marshal(Object v) throws Exception {
        return v; 
    }

}

你的根类就是这样的:

@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class SomeRoot {

    @XmlJavaTypeAdapter(MyXmlAdapter.class)
    private Object val;

    public SomeRoot(Object val) {
        this.val = val;
    }

    public SomeRoot() { }

    public Object getVal() {
        return val;
    }
}

在一个简单的main中尝试这个,在val上将提供的xml解析为String和Integer的正确类型:

public static void main(String[] args) {
        try {
            File file = new File("file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(SomeRoot.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            jaxbUnmarshaller.setAdapter(new MyXmlAdapter());

            SomeRoot pojo = (SomeRoot) jaxbUnmarshaller.unmarshal(file);
            System.out.println(pojo.getVal().getClass());
        } catch (JAXBException e) {
            e.printStackTrace();
        }

    }