Согласно документации и списку рассылки XStream, нулевые значения не включаются в вывод маршалинга - возможно, как соглашение.
A обсуждение помогло мне понять, как их отображать,Короче говоря, уловка в том, что сказал Варун: пользовательский конвертер для расширения стандартного ReflectionConverter.Идея состоит в том, чтобы перестать игнорировать события с нулевым значением и записать их в вывод.
Вот подробное объяснение того, как это сработало для меня.К сожалению, я не могу распространять окончательное решение;Я надеюсь, что следующее разблокирует многие или даже приведет к интеграции в главное дерево.
Рецепт
Вот суть моего решения, основанного на [1 ] и XStream 1.4.2:
- Расширение класса
com.thoughtworks.xstream.converters.reflection.ReflectionConverter
. - Переопределение метода
doMarshal
/ 3.Оригинальный метод игнорирует нулевые события и поэтому ничего не пишет.Новый метод должен просто взять эти события и записать то, что нужно (пустой узел, самозакрывающийся узел). - Переопределить метод
writeField
/ 5 для записи узлов с нулевым значением.Что писать, зависит от того, что требуется, и должно быть делегировано объекту записи. - Расширьте классы
com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter
и com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper
, чтобы обеспечить настраиваемый модуль записи.Для записи узла с нулевым значением требуется один метод. - Зарегистрируйте преобразователь с очень низким приоритетом (поскольку отражение является основополагающим и займет другие преобразователи).
Подробнее о подходе
Например, можно расширить модуль записи, предоставляемый с XStream, и реализовать дополнительный интерфейс:
// Context of "MyReflectionConverter"'s doMarshal method.
void writeField(...)
if (newObj == null) {
NullExtendedHierarchicalStreamWriterHelper.emptyNode(
writer.underlyingWriter(),
aliasName != null ? aliasName:
mapper.serializedMember(source.getClass(), fieldName),
fieldType);
}
else { // Rest of the original writeField method
}
}
Интерфейс здесь NullExtendedHierarchicalStreamWriter
, которыйдобавляет метод emptyNode
/ 2 к ExtendedHierarchicalStreamWriter
.Этот метод записывает нулевое значение как самозакрывающийся узел (например, для XML <int value="num"/>
, что означает num
- нулевое целое число).Приведенный выше фрагмент получает экземпляр этого писателя с помощью помощника NullExtendedHierarchicalStreamWriterHelper
, который сам является простым расширением ExtendedHierarchicalStreamWriterHelper
.Обратите внимание, что записывающее устройство, передаваемое помощнику, имеет значение writer.underlyingWriter()
, поскольку писатели упакованы, а оболочка не реализует нулевое расширение интерфейса - это означает, что мое решение остается хаком, пока не будет выполнена более глубокая интеграция.
Регистрация преобразователя обычно выполняется следующим образом:
serializer = new XStream(new MyStreamDriver());
MyReflectionConverter reflectionConverter = new
MyReflectionConverter(serializer.getMapper(),
serializer.getReflectionProvider());
serializer.registerConverter(reflectionConverter, XStream.PRIORITY_VERY_LOW);
Здесь представляет собой разность указанного выше пользовательского преобразователя отражения, в отличие от исходного кода.Пожалуйста, учтите, что это расширение, которое не является частью основного дерева, и оно гораздо менее проверено, чем исходный код.На сегодняшний день он проходит тестовые наборы.