Настройка обработки ошибок немаршальского процесса JAXB

Принятие у меня есть схема, которая описывает корневой класс элемента Root это содержит a List<Entry> где Entry класс имеет имя обязательного поля.

Вот то, как это смотрит в коде:

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();
}

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;
}

Если я предоставляю следующий XML для немаршалинга:

<root>
  <entry>
    <name>ekeren</name>
  </entry>
  <entry>
  </entry>
</root>

У меня есть проблема, потому что вторая запись не содержит имя. Таким образом, неМаршалл производит null.

Есть ли способ настроить JAXB в неМаршалл a Root объект, который будет только содержать "хорошую" запись?

5
задан falsarella 2 February 2012 в 11:25
поделиться

1 ответ

Вы можете добавить магический метод afterUnmarshal, чтобы позаботиться о пустых записях:

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    Iterator<Entry> iter = entries.iterator();
    while (iter.hasNext()) {
      if (iter.next().name == null) iter.remove();
    }
  }
}

EDIT:

Не уверен, что это лучше подходит для вас, но, возможно, это поможет. Вы также можете использовать Pacher, например, если не все объекты, необходимые для исправления/подтверждения результата, доступны в afterUnmarshal(...)

Выполняется UnmarshallingContext после завершения парсинга. В основном используется для разрешения прямых IDREF, но может выполнять любое действие. (javadoc)

Вот пример:

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;

  private boolean isValidEntry() {
    return name != null;
  }

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    if (!isValidEntry()) {
      // entry not yet added to parent - use a patcher
      UnmarshallingContext.getInstance().addPatcher(new Patcher() {
        public void run() throws SAXException {
          ((Root)parent).removeEntry(this);
        }
      });
    }
  }
}

Однако я бы не стал слишком злоупотреблять этим, не только потому, что это API только для Sun.

Но если вам действительно нужно что-то настраиваемое, что не является частью кода самих маршалируемых объектов. Возможно, лучше посмотреть на что-то после размаршалинга. Интересно, не подойдет ли вам Bean Validation (JSR 303), например, использование Hibernate Validator (не пугайтесь названия, вам не нужен Hibernate ORM для его использования). Сам я его не использовал, но использование (нового) стандарта для валидации звучит разумно, не так ли?

5
ответ дан 14 December 2019 в 19:06
поделиться
Другие вопросы по тегам:

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