XStream не игнорирует неизвестные элементы при использовании JavaBeanConverter

Я использую XStream 1.4.7 для обработки десериализации POJO. По мере развития проекта мне нужно будет добавлять новые функции и, следовательно, новые поля класса. Я бы хотел, чтобы старые версии приложения изящно обрабатывали эти изменения и игнорировали неизвестные теги.

xs = new XStream();
xs.setMode(XStream.NO_REFERENCES);
xs.ignoreUnknownElements();
xs.registerConverter(new JavaBeanConverter(xs.getMapper(),
    new TransientRespectingBeanProvider()), XStream.PRIORITY_VERY_LOW);

Вчера я добавил поле String в один из своих классов и сериализовал его. Старая версия приложения не могла десериализовать xml.

com.thoughtworks.xstream.converters.ConversionException: No field 'materialNrVersion' found in class 'com.company.ProjectConfiguration' : No field 'materialNrVersion' found in class 'com.company.ProjectConfiguration'
---- Debugging information ----
message             : No field 'materialNrVersion' found in class 'com.company.ProjectConfiguration'
cause-exception     : com.thoughtworks.xstream.converters.reflection.MissingFieldException
cause-message       : No field 'materialNrVersion' found in class 'com.company.ProjectConfiguration'
class               : com.company.ProjectConfiguration
required-type       : com.company.ProjectConfiguration
converter-type      : com.thoughtworks.xstream.converters.javabean.JavaBeanConverter
line number         : 192
version             : 1.4.7

Должен ли я делать это по-другому?

ОБНОВЛЕНИЕ Если я закомментирую вызов registerConverter, неизвестные поля будут проигнорированы. Похоже, что JavaBeanConverter влияет на то, как обрабатывается ignoreUnknownElements. TransientRespectingBeanProvider предназначен для игнорирования свойств, которые имеют аннотацию @Transient.

Может ли кто-нибудь предложить решение или обходной путь? Альтернативный подход к проблеме @Transient?


person paul    schedule 17.09.2015    source источник


Ответы (1)


Исходный код xStream достаточно ясен и прост. Вы можете создать подкласс JavaBeanConverter и настроить его метод unmarshal, а также зарегистрировать измененный преобразователь для некоторых или всех ваших классов. В частности, если вы посмотрите на исходный код JavaBeanConverter.unmarhal(), там

if (propertyExistsInClass) {
    ...
} else {
    throw new MissingFieldException(resultType.getName(), propertyName);
}

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

person Jan X Marek    schedule 19.12.2015