Jackson:自定义反序列化器:无法使用数组反序列化XML

时间:2020-02-12 10:43:21

标签: java json xml jackson deserialization

我使用Jackson来将我的一个类序列化为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 :(得分:0)

[已编辑]

几年前,我遇到了同样的问题。 默认情况下,杰克逊(最特别是UntypedObjectDeserializer)看到多个具有相同名称的子项时,不会将它们映射到数组或列表中。 我所做的是我使用了这个库:https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.json%22%20AND%20a%3A%22json%22 这样就可以做到:

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

当然,这是一个附加的解析然后序列化的步骤,然后您才可以实际反序列化为Jackson节点。 上面的代码对我来说很好,因为它不在应用程序的关键路径上。

[编辑]

在需要在反序列化器中使用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