如何使JAXB Marshaller根据其运行时类型编组抽象类?

栏目: Java · 发布时间: 6年前

内容简介:翻译自:https://stackoverflow.com/questions/11368076/how-to-make-jaxb-marshaller-marshal-abstract-class-based-on-its-runtime-type

考虑以下抽象类 –

public abstract class Car
{
    public abstract void drive(double miles);
}

这是扩展上述类的示例类(用于说明目的).

public class Ferrari extends Car
{
    private String lastUsed; // Ferrari specific field not in Car
    private boolean f1Car;   // Ferrari specific field not in Car

    @XmlElement
    public void setF1Car(boolean f1Car)
    {
        this.f1Car = f1Car;
    }

    public boolean isF1Car() { return f1Car; }

    @XmlElement
    public void setLastUsed(String lastUsed)
    {
        this.lastUsed = lastUsed;
    }

    public String getLastUsed() { return lastUsed; }

    public void drive(double miles)
    {
        // implementation
    }
}

我有一个包含Car对象的报表类 –

@XmlRootElement
public class CarTestReport
{
    private String date;
    private double miles;
    private Car car;

    @XmlElement
    public void setDate(String date) { this.date = date;}

    public String getDate() {return date;}

    @XmlElement
    public void setMiles(double miles) { this.miles = miles; }

    public double getMiles() {return miles;}

    @XmlElement
    public void setCar(Car car) { this.car = car; }

    public Car getCar() { return car; }
}

这里是使用JAXB来传递CarTestReport对象的代码片段 –

public static void main(String[] args) throws Exception
{
    Ferrari ferrari = new Ferrari();
    ferrari.setLastUsed("July 5 2012");
    ferrari.setF1Car(false);

    CarTestReport  report = new CarTestReport();
    report.setDate("July 6 2012");
    report.setMiles(200);
    report.setCar(ferrari);

    File file = new File("carTestReport.xml");
    JAXBContext jaxbContext = JAXBContext.newInstance(CarTestReport.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    jaxbMarshaller.marshal(report, file);
}

问题是,由于Car的抽象类型,JAXB忽略它并且在它对CarTestReport对象进行编组时不会对法拉利对象进行编组.我得到的输出是 –

<carTestReport>
  <car/>
  <date>July 6 2012</date>
  <miles>200.0</miles>
</carTestReport>

如您所见,即使填充了法拉利对象,也没有在“汽车”节点下输入任何内容.如何解决这个问题呢?

对于任何可能的JAXB注释类,JAXB系统都不会查看类路径.你必须帮助它找到它们.在您的示例代码中,它根本不知道法拉利类的存在. (它只能看到Car,因为这是CarTestReport中getter的返回类型.)

告诉JAXB关于法拉利的一种快速而肮脏的方法是在Car类的顶部添加@XmlSeeAlso({Ferrari.class}).然后你会得到这样的输出:

<carTestReport>
  <car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ferrari">
    <f1Car>false</f1Car>
    <lastUsed>July 5 2012</lastUsed>
  </car>
  <date>July 6 2012</date>
  <miles>200.0</miles>
</carTestReport>

告诉JAXB关于法拉利的另一种方法是将该类传递给JAXBContext.newInstance方法,即:

JAXBContext jaxbContext = JAXBContext.newInstance(CarTestReport.class,
        Ferrari.class);

或者,如果所有JAXB类都在同一个包中,例如com.mycompany.carstuff,然后你可以这样做:

JAXBContext jaxbContext = JAXBContext.newInstance("com.mycompany.carstuff");

在最后一种情况下,它将搜索该包中的所有类.

如果你想让它发出一个名为ferrari的元素(而不是像上面那样的<car xsi:type =“ferrari”>),一种可能性是将@XmlType添加到你的Car类的顶部,如下所示:

import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;

@XmlSeeAlso({Ferrari.class})
@XmlType
public abstract class Car {
  public abstract void drive(double miles);
}

…并将@XmlRootElement放在法拉利上,例如:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Ferrari extends Car {
  // ...
}

根据我的理解,这种注释组合告诉JAXB Car类映射到XML模式类型(因此你不会得到任何名为“car”的元素),并且法拉利类是该类型的元素(所以你可以有名为“ferrari”的元素. @XmlRootElement中的“根”是误导性的…它可以是对象结构中的任何元素.

翻译自:https://stackoverflow.com/questions/11368076/how-to-make-jaxb-marshaller-marshal-abstract-class-based-on-its-runtime-type


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

领域特定语言

领域特定语言

Martin Fowler / ThoughtWorks中国 / 机械工业出版社华章公司 / 2013-3 / 89.00元

本书是DSL领域的丰碑之作,由世界级软件开发大师和软件开发“教父”Martin Fowler历时多年写作而成,ThoughtWorks中国翻译。全面详尽地讲解了各种DSL及其构造方式,揭示了与编程语言无关的通用原则和模式,阐释了如何通过DSL有效提高开发人员的生产力以及增进与领域专家的有效沟通,能为开发人员选择和使用DSL提供有效的决策依据和指导方法。 全书共57章,分为六个部分:第一部分介......一起来看看 《领域特定语言》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器