Как заставить JAXB Marshaller маршалировать абстрактный класс на основе его типа времени выполнения?

Рассмотрим следующий абстрактный класс-

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 игнорирует его и не маршалирует объект Ferrari, когда он маршалирует объект CarTestReport. Вывод, который я получаю, таков-

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

Как видите, под узлом «автомобиль» ничего не было введено, хотя объект «Феррари» был заполнен. Как решить эту проблему?

7
задан tftd 1 December 2016 в 23:09
поделиться