Как правильно использовать @XmlJavaTypeAdapter для корневого объекта с помощью JAXB (JDK 8)?JAVA

Программисты JAVA общаются здесь
Anonymous
Как правильно использовать @XmlJavaTypeAdapter для корневого объекта с помощью JAXB (JDK 8)?

Сообщение Anonymous »

Я пытаюсь маршалировать корневой объект в XML с помощью JAXB (встроенная реализация в JDK 8u472). Чтобы управлять структурой вывода, я написал XmlAdapter, который адаптирует Root во вложенный класс MiddleRoot.Упрощенный код
@XmlJavaTypeAdapter(RootAdapter.class)
public class Root {
private String a, b, c, d, e;
// getters/setters...
}

public class RootAdapter extends XmlAdapter {
// marshal: Root -> MiddleRoot
// unmarshal: MiddleRoot -> Root
}

@XmlRootElement(name = "root")
public class MiddleRoot{
@XmlElement(name = "head")
private Head head;
@XmlElement(name = "body")
private Body body;

static class Head{
private String a,b,c;
// getter and setter
}

static class Body{
private String d,e;
// getter and setter
}

// getter and setter
}

Код маршаллинга
JAXBContext context = JAXBContext.newInstance(Root.class, MiddleRoot.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(root, System.out);

ОШИБКА
javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: class "com.ff.Root" nor any of its super class is known to this context or lacks a @XmlRootElement]

Что я обнаружил при отладке

Отслеживание исходного кода JAXB (com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl) показывает:
  • Root не имеет аннотации @XmlRootElement, поэтому его elementName становится нулевым.
  • Во время создания JAXBContext ClassInfoImpl.parseElementName возвращает значение null, а позднее tagName имеет значение null при вызове сериализацииRoot.
  • Обработка @XmlJavaTypeAdapter, похоже, не предоставляет имя корневого элемента.

Мои вопросы
  • Правильно ли я использую @XmlJavaTypeAdapter в корневом классе, или корневому классу всегда нужен @XmlRootElement?
  • Если мне нужно добавить @XmlRootElement в Root, будет ли адаптер по-прежнему вызываться?

Желаемый результат


a
b

c


d
e



Дополнительные сведения об отладке
1. Exception thrown in com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot because tagName is null.
2. tagName is assigned in the ClassBeanInfoImpl constructor via ci.isElement(), which checks whether RuntimeClassInfo.elementName is null.
3. elementName is determined in ModelBuilder.getClassInfo ClassInfoImpl.parseElementName: it returns null if the class has no @XmlRootElement.

Вернуться в «JAVA»