Дублированное поле в сгенерированном XML с использованием JAXB
Это мой сценарий. У меня есть общий класс:
public class Tuple<T> extends ArrayList<T> {
//...
public Tuple(T ...members) {
this(Arrays.asList(members));
}
@XmlElementWrapper(name = "tuple")
@XmlElement(name = "value")
public List<T> getList() {
return this;
}
}
И детский класс:
public class StringTuple extends Tuple<String> {
public StringTuple(String ...members) {
super(members);
}
//explanation of why overriding this method soon ...
@XmlElementWrapper(name = "tuple")
@XmlElement(name = "value")
@Override
public List<String> getList() {
return this;
}
}
Эти классы упоминаются здесь:
@XmlRootElement(namespace = "iv4e.xml.jaxb.model")
public class Relation {
private Tuple<StringTuple> relationVars;
//...
@XmlElementWrapper(name = "allRelationVars")
@XmlElement(name = "relationVarsList")
public Tuple<StringTuple> getRelationVars() {
return relationVars;
}
}
Затем создается объект Relation с чем-то вроде:
Relation rel = new Relation();
rel.setRelationVars(new Tuple<StringTuple>(
new StringTuple("RelationshipVar1"), new StringTuple("RelationshipVar2")));
После маршалинга этого объекта вывод Xml будет следующим:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:relation xmlns:ns2="iv4e.xml.jaxb.model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">
<allRelationVars>
<relationVarsList>
<tuple>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">RelationshipVar1</value>
</tuple>
<tuple>
<value>RelationshipVar1</value>
</tuple>
</relationVarsList>
<relationVarsList>
<tuple>
<value xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">RelationshipVar2</value>
</tuple>
<tuple>
<value>RelationshipVar2</value>
</tuple>
</relationVarsList>
</allRelationVars>
</ns2:relation>
Итак value
элементы дублируются!
Теперь причина, по которой класс StringTuple переопределяет List<T> getList()
с List<String> getList()
избегает раздражающей сгенерированной xmlns:xs
атрибуты в каждом члене списка (value
элементы в документе XML). Но тогда каждый член списка отображается дважды в выводе. Очевидно, это потому, что как переопределенный родительский метод, так и дочерний метод аннотированы @XmlElement
, Поэтому мой главный вопрос: есть способ игнорировать переопределенные методы, аннотированные @XmlElement
в яксбе? (учитывая, что метод переопределения также помечен @XmlElement
)
Я обнаружил, что в старой публикации сообщалось о похожей проблеме: http://old.nabble.com/@XmlElement-on-overridden-methods-td19101616.html, но я пока не нашел решения. Также обратите внимание, что добавление @XmlTransient
аннотация к getList
метод в родительском классе (Tuple<T>
) может решить эту проблему, но создаст другие, поскольку родительский класс не является абстрактным и используется один в других контекстах.
Односторонний вторичный вопрос: можно ли объявить xmlns:xs
атрибут в корневом узле вместо него - раздражающе - появляется в каждом узле, где это необходимо? Я знаю, что это можно сделать с NamespacePrefixMapper
класс, но, поскольку это нестандартный внутренний класс SUN, я предпочитаю использовать более независимый от реализации подход.
Заранее спасибо за любые отзывы!
2 ответа
Вы можете использовать следующий подход маркировки собственности @XmlTransient
на родителя и @XmlElement
на ребенка:
родитель
package forum7851052;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlRootElement
public class Parent<T> {
private List<T> item = new ArrayList<T>();
@XmlTransient
public List<T> getItem() {
return item;
}
public void setItem(List<T> item) {
this.item = item;
}
}
IntegerChild
package forum7851052;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class IntegerChild extends Parent<Integer> {
@Override
@XmlElement
public List<Integer> getItem() {
return super.getItem();
}
@Override
public void setItem(List<Integer> item) {
super.setItem(item);
}
}
StringChild
package forum7851052;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class StringChild extends Parent<String> {
@Override
@XmlElement
public List<String> getItem() {
return super.getItem();
}
@Override
public void setItem(List<String> item) {
super.setItem(item);
}
}
демонстрация
package forum7851052;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Parent.class, IntegerChild.class, StringChild.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
IntegerChild integerChild = new IntegerChild();
integerChild.getItem().add(1);
integerChild.getItem().add(2);
marshaller.marshal(integerChild, System.out);
StringChild stringChild = new StringChild();
stringChild.getItem().add("A");
stringChild.getItem().add("B");
marshaller.marshal(stringChild, System.out);
}
}
Выход
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<integerChild>
<item>1</item>
<item>2</item>
</integerChild>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<stringChild>
<item>A</item>
<item>B</item>
</stringChild>
Это может быть довольно старым, но это первый результат при поиске "JAXB дубликаты полей"
Наткнулся на ту же проблему, это помогло мне:
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE) // <-- made the difference
public abstract class ParentClass
{
...
}
@XmlRootElement
public class ChildClass extends ParentClass
{
...
}