xStream JSON - как обрабатывать нулевые значения - PullRequest
0 голосов
/ 24 октября 2011

У меня есть этот пример json:

{
    "rows": [
        {
            "anaid": "1",
            "anaint": "123",
            "anastring": "-"
        },
        {
            "anaid": "2",
            "anaint": "-",
            "anastring": "Hello World"
        },
        {
            "anaid": "3",
            "anaint": "-",
            "anastring": "-"
        }
    ]
}

где в моем классе Test находятся:

  • int anaid
  • int anaint
  • String anastring

Мой код Java:

XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.alias("rows", Test.class);
ArrayList<Test> product = (ArrayList<Test>) xstream.fromXML(json);

Таким образом, символ "-" является нулевым значением для моего JSON.Я не могу изменить код для создания json, но я бы обработал нулевое значение "-", чтобы правильно использовать мой анализатор xStream.

Ответы [ 3 ]

0 голосов
/ 13 декабря 2011

Согласно документации и списку рассылки XStream, нулевые значения не включаются в вывод маршалинга - возможно, как соглашение.

A обсуждение помогло мне понять, как их отображать,Короче говоря, уловка в том, что сказал Варун: пользовательский конвертер для расширения стандартного ReflectionConverter.Идея состоит в том, чтобы перестать игнорировать события с нулевым значением и записать их в вывод.

Вот подробное объяснение того, как это сработало для меня.К сожалению, я не могу распространять окончательное решение;Я надеюсь, что следующее разблокирует многие или даже приведет к интеграции в главное дерево.

Рецепт

Вот суть моего решения, основанного на [1 ] и XStream 1.4.2:

  1. Расширение класса com.thoughtworks.xstream.converters.reflection.ReflectionConverter.
  2. Переопределение метода doMarshal / 3.Оригинальный метод игнорирует нулевые события и поэтому ничего не пишет.Новый метод должен просто взять эти события и записать то, что нужно (пустой узел, самозакрывающийся узел).
  3. Переопределить метод writeField / 5 для записи узлов с нулевым значением.Что писать, зависит от того, что требуется, и должно быть делегировано объекту записи.
  4. Расширьте классы com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter и com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper, чтобы обеспечить настраиваемый модуль записи.Для записи узла с нулевым значением требуется один метод.
  5. Зарегистрируйте преобразователь с очень низким приоритетом (поскольку отражение является основополагающим и займет другие преобразователи).

Подробнее о подходе

Например, можно расширить модуль записи, предоставляемый с 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);

Здесь представляет собой разность указанного выше пользовательского преобразователя отражения, в отличие от исходного кода.Пожалуйста, учтите, что это расширение, которое не является частью основного дерева, и оно гораздо менее проверено, чем исходный код.На сегодняшний день он проходит тестовые наборы.

0 голосов
/ 11 февраля 2013

Для меня самый простой способ - получить исходный код, скопировать класс ReflexionConverted и в метод public void marshal (Оригинал объекта, конечный писатель HierarchicalStreamWriter, конечный контекст MarshallingContext) ...

у вас есть:

reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
    public void visit(String fieldName, Class fieldType, Class definedIn, Object newObj) {
        if (newObj != null) {
            ...
            complete the else method with your code...for example:

        } else {
            Object obj = new String("");

            writeField(fieldName, fieldType, definedIn, obj);
            seenFields.add(fieldName);

        }
    }
}
0 голосов
/ 24 октября 2011

Используйте пользовательский конвертер. Учебное пособие здесь

...