Почему это невозможно? Кажется, все так просто, но не работает так, как ожидалось.
Резюме: Класс A использует агрегированный компонент DataA, тогда как класс B (подкласс класса A) использует агрегированный компонент DataB (тогда как DataB расширяет DataA).
Я написал эти тестовые классы для визуализации и объяснения моего вопроса:
Класс A:
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class A {
private DataA source = new DataA();
@XmlElement(name="source")
public DataA getSource() {
return source;
}
public void setSource(DataA source) {
this.source = source;
}
}
и его класс DataA (я использовал аннотацию FIELD, чтобы все поля были распределены):
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@XmlAccessorType(XmlAccessType.FIELD)
public class DataA {
public String string1 = "1";
public String string2 = "2";
}
А теперь класс B (подкласс класса A): Моя цель состоит в том, чтобы повторно использовать функциональные возможности A, а также повторно использовать свойства из компонента DataA с помощью компонента DataB:
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class B extends A {
private DataB source = new DataB();
public DataB getSource() {
return this.source;
}
public void setSource(DataB source) {
this.source = source;
}
}
Соответствующий ему компонент DataB выглядит следующим образом:
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@XmlAccessorType(XmlAccessType.FIELD)
public class DataB extends DataA {
public String string3 = "3";
}
Теперь, когда я собираю экземпляр класса A, он выдает следующее:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
</source>
</root>
Когда я собираю экземпляр класса B, я получаю тот же результат:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
</source>
</root>
Но я ожидал, что string3 тоже будет маршализованным, но он только записывает свойства компонента DataA! ЗАЧЕМ? Это не совсем интуитивно, если думать с точки зрения ООП.
Когда я устанавливаю аннотацию @XmlElement также для класса B ... вот так:
@XmlElement
public DataB getSource() {
return this.source;
}
... тогда свойство дважды упорядочивается, поскольку оно аннотируется как родительским классом, так и дочерним классом. Это также то, что я не хочу:
Теперь вывод:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source xsi:type="dataB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
<source>
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
</root>
В результате я ожидал от JAXB следующего XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
</root>
Есть какие-нибудь подсказки, как настроить JAXB для получения ожидаемого результата?
Спасибо за любой отзыв.