Немаршалинг наборов в JaxB

В ES7 вы можете сделать элегантный ENUM, опираясь на статические атрибуты:

class ColorEnum  {
    static RED = 0 ;
    static GREEN = 1;
    static BLUE = 2;
}

, затем

if (currentColor === ColorEnum.GREEN ) {/*-- coding --*/}

Преимущество (использование класса вместо литеральный объект) должен иметь родительский класс Enum, тогда все ваши Enums будут расширять этот класс.

 class ColorEnum  extends Enum {/*....*/}

14
задан Stas 23 June 2009 в 12:06
поделиться

5 ответов

JAXB имеет проблемы с поддержкой интерфейсов и абстрактных классов; обычно он не знает, какой подкласс создать. Проблема в том, что обычно класс имеет следующий вид:

ArrayList list;

@XMLElement
public List getList() {return this.list;}

Чтобы обойти это, JAXB даже не пытается создать экземпляр класса свойств (например, List), полученного из пары получателей / установщиков, если это Коллекция. Он просто предполагает, что он не равен NULL и может быть изменен.

Вероятно, самый простой способ - пометить свой бизнес-интерфейс с помощью @XMLTransient и добавить другую пару получателей / сеттеров с помощью @XMLElement для представления для данных, которые вы хотите раскрыть. в JAXB. Я обычно делаю их защищенными, а не общедоступными, потому что я не хочу иметь несколько глупое поведение JAXB как часть открытого контракта моих классов.

3
ответ дан 1 December 2019 в 12:13
поделиться

именно так jaxb обрабатывает коллекции. вы должны быть уверены, что у вас есть ненулевая коллекция, когда jaxb пытается демаршалировать.

есть плагин (никогда не использовал его сам), но он может быть полезным: https://jaxb2-commons.dev.java.net/collection-setter-injector/

8
ответ дан 1 December 2019 в 12:13
поделиться

Эй,

Вы можете использовать его с jaxb, это работает!!!! (с Maven....)

<plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <args>
                    <arg>-Xcollection-setter-injector</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>net.java.dev.vcc.thirdparty</groupId>
                        <artifactId>collection-setter-injector</artifactId>
                        <version>0.5.0-1</version>
                    </plugin>
                </plugins>
                <schemaDirectory>src/schemas</schemaDirectory>
                <generateDirectory>src/main/java</generateDirectory>
                <extension>true</extension>
            </configuration>
        </plugin>

и вы получите свой сеттер для вашей коллекции

Надеюсь, это поможет людям

пока

.
6
ответ дан 1 December 2019 в 12:13
поделиться

Jaxb2 UnMarshaller определяет интерфейс слушателя, который вызывается каждый раз, когда объект не маршалируется. Вы можете определить настраиваемый прослушиватель для вызова методов установки для всех коллекций (или для подобъектов). Это должно быть довольно легко сделать с любым из классов bean-компонентов. Я ищу существующую реализацию, но не вижу ее.

JAXBContext context = JAXBContext.newInstance( classesToBeBound );
m_unmarshaller = context.createUnmarshaller();
m_unmarshaller.setListener(
  new Unmarshaller.Listener() {
    public void afterUnmarshal(Object target, Object parent) {
     for (Property p : getBeanProperties(target.getClass()))
      if (p.isCollectionType() || p.isCompositeType())
        p.invokeSetter(p.invokeGetter());
    }
  });

Если вы используете платформу Spring, это довольно просто:

    new Unmarshaller.Listener() {
         public void afterUnmarshal(Object target, Object parent) {
             BeanWrapper wrapper = new BeanWrapperImpl(target);
             for (PropertyDescriptor pd : wrapper.getPropertyDescriptors()) {
                 if (pd.getPropertyType() != null) {
                         if (!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
                             try {
                                 Method setter = pd.getWriteMethod();
                                 if (setter != null) {
                                     Method getter = pd.getReadMethod();
                                     if (getter != null)
                                         setter.invoke(target, getter.invoke(target));
                                 }
                             }
                             catch (Exception ex) {
                                 s_logger.error("can't invoke setter", ex);
                             }
                         }
                 }
             }
         }
    }
1
ответ дан 1 December 2019 в 12:13
поделиться

Вы можете просто использовать массив вместо списка)

1
ответ дан 1 December 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: