JAXB — Установить XmlAdapter только для определенного подтипа элемента?

#xml #xml-serialization #jaxb

#xml #xml-сериализация #jaxb

Вопрос:

Я должен сгенерировать xml-элемент, который может иметь в качестве значения любой «примитивный тип» (xsd: string, xsd: boolean и т. Д.). Примеры:

 <field xsi:type="xsd:string" name="aString">String Value</field>
<field xsi:type="xsd:dateTime" name="aDate">2011-10-21</field>
<field xsi:type="xsd:dateTime" name="aDateTime">2011-10-21T12:00:00</field>
...
 

Итак, я использую эту реализацию, которая заставляет JAXB определять xsi:type тип примитива:

 public class Field {
    @XmlAttribute
    private String name;

    @XmlElement
    Object value;
}
 

и он работает, как ожидалось, но все java.util.Дата получает тип xs:dateTime

Теперь я хочу изменить поведение маршаллера ТОЛЬКО тогда, когда объект ‘value’ является экземпляром java.util.Дата для получения таких полей:

 <field xsi:type="xsd:date" name="aDate">2011-10-21</field>
<field xsi:type="xsd:dateTime" name="aDateTime">2011-10-21T12:00:00</field>
 

Итак, я создаю адаптер, но если я попробую это:

 @XmlElement
@XmlJavaTypeAdapter(DateAdapter.class)
Object value;
 

Адаптер должен обрабатывать java.lang.Тип объекта

 public class DateAdapter extends XmlAdapter<String, Object> {...}
 

Но я не хочу терять маршаллеры JAXB для всех остальных объектов (Integer, Double и т. Д.)…

есть способ установить адаптер для определенного подтипа элемента?

Комментарии:

1. Вы нашли какое-либо решение для этого?

2. На самом деле нет… У меня есть адаптер, который обрабатывает класс объекта и внутренне управляет каждым подтипом. Это не «приятно», но это работает.

Ответ №1:

Я столкнулся с аналогичной ситуацией, хотя я исходил из XSD и генерировал классы оттуда. Тем не менее, решение также должно быть доступно для вас.

В моих случаях я хотел расширить использование простой строки в модели XSD, чтобы она отображалась как UUID в коде Java, затем другая отображалась как класс в других местах и так далее. Сторона XML, это все string (xs:string), так как же разделить все эти строки на отдельные типы на стороне java…

Что я закончил, так это то, что в XSD я создал простые типы для каждого случая, здесь объявление UUID :

И используйте это вместо строки везде, где требуется.

Затем я создал файл привязок, в котором я указал свои XmlAdaptors, как и вы, за исключением того, что теперь у меня есть отдельные цели и, следовательно, я могу использовать несколько адаптеров, предназначенных специально для каждого xml «types».

Теперь у вас есть дополнительная трудность, заключающаяся в том, что на стороне Java представление вашего поля является просто объектом. Я полагаю, вы затем применяете его, как только узнаете атрибут type. Возможно, создание подкласса field для каждого случая, это позволит вам изменить объявление typeADaptor .

Ответ №2:

попробуйте

http://jaxb.java.net/guide/Mapping_interfaces.html#Use__XmlJavaTypeAdapter

XmlJavaTypeAdapter для интерфейсов с несколькими реализациями

Комментарии:

1. -1 Вы прочитали вопрос? Я реализовал a XmlAdapter<String, Object> , но при этом я потерял адаптер для Integer, Double, etc . Я хочу сохранить эти адаптеры, и, очевидно, если я использую адаптер для объекта, проще всего сгенерировать xsi:anyType , но это именно то, чего я не хочу

2. Что касается вашего решения «несколько реализаций», это означает, что я должен обрабатывать Object и адаптировать и реализовывать оболочку для каждого подкласса объектов, чтобы сгенерировать правильный xsi:type . Опять же, здесь я теряю адаптеры, которые хочу сохранить.