java - JAXB 解码派生类型

标签 java xml jaxb

根据以下程序,它会正确打印出我们期望的内容。 如果使用 ClassA 和 ClassB 类,这样的程序是否可以正确解码 相同的 XmlRootElement 名称?例如,如果它们都被定义为“typeA”...?可不可能是 可以用 JAXB 做类似的事情吗?

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Date;

public class JaxbABCTest {
    public static void main(String[] args) throws JAXBException, UnsupportedEncodingException {
        final JAXBContext context = JAXBContext.newInstance(ABC.class);
        final Marshaller marshaller = context.createMarshaller();
        final Unmarshaller unmarshaller = context.createUnmarshaller();

        ABC class1 = new ClassA();
        ABC class2 = new ClassB();

        final ByteArrayOutputStream baosA = new ByteArrayOutputStream();
        final ByteArrayOutputStream baosB = new ByteArrayOutputStream();

        // Marshall to XML
        marshaller.marshal(class1, baosA);
        marshaller.marshal(class2, baosB);

        String xmlA = baosA.toString(Charset.defaultCharset().name());
        String xmlB = baosB.toString(Charset.defaultCharset().name());

        System.out.println(xmlA);
        System.out.println(xmlB);

        // Now attempt the reverse.
        Object unmarshalA = unmarshaller.unmarshal(new StringReader(xmlA));
        Object unmarshalB = unmarshaller.unmarshal(new StringReader(xmlB));

        System.out.println(unmarshalA.getClass());
        System.out.println(unmarshalB.getClass());
    }
}

@XmlTransient
@XmlSeeAlso({
    ClassA.class,
    ClassB.class
})
abstract class ABC {
    private int a;

    @XmlAttribute
    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

@XmlRootElement(name = "typeA")
class ClassA extends ABC {
    private String b;
    private Date c;

    @XmlAttribute
    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    @XmlAttribute
    public Date getC() {
        return c;
    }

    public void setC(Date c) {
        this.c = c;
    }
}

@XmlRootElement(name = "typeB")
class ClassB extends ABC {
    private String b;
    private Date c;
    private boolean d;
    private float e;

    @XmlAttribute
    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    @XmlAttribute
    public Date getC() {
        return c;
    }

    public void setC(Date c) {
        this.c = c;
    }

    @XmlAttribute
    public boolean isD() {
        return d;
    }

    public void setD(boolean d) {
        this.d = d;
    }

    @XmlAttribute
    public float getE() {
        return e;
    }

    public void setE(float e) {
        this.e = e;
    }
}

最佳答案

对于简单的 JAXB 解码,(根)一个元素名称是指具有映射到某个 Java 类的特定结构的元素。

当然,您可以定义一个包含 A 和 B 字段并集的类 - 只要两个类中出现的字段匹配即可。你必须有一些属性来让你决定它到底是两个“子类”中的哪一个。 (这在本质上类似于使用 XPath 表达式,其中包括对属性或元素是否存在(甚至值)的测试。)

您还可以采用更复杂的方法,在读取 XML 后保留此元素,调查 DOM 树并根据检测到的内容创建 JAXBContext。这将允许您使用与 XML 内容完全匹配的 Java 类型的相同元素名称。当然,必须有一个明确的标准,并且您必须编写基于原始 DOM 树数据进行分析的代码。

关于java - JAXB 解码派生类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27395788/

相关文章:

java - 如何记录契约(Contract)最后(通过 jaxb schemagen)web 服务?

java - Java 中另一个令人困惑的泛型

java - 如何以编程方式告诉 Logback 重新加载配置

c# - 根级别的数据无效

java - 如何获取代表具有特定 [property,object] 对的对象的 RDF 资源?

java - @Consumes( {"application/xml,application/json"}) 如何编程返回类型

java - 针对 XSD 的 XML 无效

java - 下载文件中的 UTF-8 编码名称

java - 在 java 中,有没有办法确保在 finally block 中调用多个方法?

c# - Nuget nuspec 不适用于通配符