Джексон: пользовательский десериализатор: не может десериализовать XML с массивом - PullRequest
0 голосов
/ 12 февраля 2020

Я использую Джексона для сериализации одного из моих классов как XML. Из-за сложной внутренней структуры я использую специальный сериализатор, который генерирует эти данные в виде массива.

Полученный XML выглядит так в упрощенном примере:

<MyDataType>
    <list>
        <entry>
            <order>0</order>
            <value>And then a step to the right</value>
        </entry>
        <entry>
            <order>1</order>
            <value>It's just a jump to the left</value>
        </entry>
        <entry>
            <order>2</order>
            <value>With your hands on your hips</value>
        </entry>
    </list>
</MyDataType>

Я только получить проблемы, когда я десериализую. Тогда jsonParser.getCodec().readTree(jsonParser) просто «видит» последнюю запись массива. Все остальные записи потеряны.

Так что вывод отладки в десериализаторе покажет:

Deserialize: Incoming data:
{
    "list": {
        "entry": {
            "order": "2",
            "value": "With your hands on your hips"
        }
    }
}

Еще более странно: если я сериализую / десериализую в JSON, то тоже самое код работает отлично!

Десериализатор:

class MyDataTypeDeserialize extends JsonDeserializer<MyDataType> {
    @Override
    public MyDataType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        MyDataType result = new MyDataType();

        JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser);

        // Shows only one entry when using XML
        System.out.println("Deserialize: Incoming data: " + rootNode.toString());

        JsonNode valueList = rootNode.get("list");
        JsonNode entryList = valueList.findValue("entry");

        for (Iterator<JsonNode> it = entryList.elements(); it.hasNext(); ) {
            JsonNode element = it.next();

            int order = element.get("order").asInt();
            String value = element.get("value").asText();

            result.addValue(order, value);
        }

        return result;
    }
}

Любые намеки на то, что я делаю неправильно, будут оценены.

1 Ответ

0 голосов
/ 12 февраля 2020

[Отредактировано]

Я столкнулся с той же проблемой пару лет назад. По умолчанию Джексон (в частности, UntypedObjectDeserializer), когда видит несколько дочерних элементов с одинаковыми именами, не отображает их в массив или список. Я использовал эту библиотеку: https://search.maven.org/classic/#search% 7Cgav% 7C1% 7Cg% 3A% 22org.json% 22% 20AND% 20a% 3A% 22json% 22 * ​​1007 * С этим вы можете сделать:

JSONObject jsonObject = XML.toJSONObject(...);
String jsonText = jsonObject.toString();
// Use Jackson here

Конечно, это дополнительный шаг синтаксического анализа и затем сериализации, прежде чем вы сможете фактически десериализоваться как узел Джексона. Вышесказанное работало хорошо для меня, потому что это не было на критическом пути приложения.

[Edit]

В вашем случае, когда вам нужно использовать JsonParser в десериализаторе вы можете попробовать что-то вроде этого:

JsonLocation start = jp.getCurrentLocation();
jsonParser.getCodec().readTree(jsonParser); // The result is ignored
JsonLocation end = jp.getCurrentLocation();

String xmlText = end.getSourceRef().toString().substring(start.getCharOffset() - 1, end.getCharOffset());

JSONObject jsonObject = XML.toJSONObject(xmlText);
String jsonText = jsonObject.toString();

// Parse jsonText into JsonNode

Или альтернативное решение: https://github.com/DinoChiesa/deserialize-xml-arrays-jackson/blob/master/src/main/java/com/google/xmldeser/ArrayInferringUntypedObjectDeserializer.java

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...