FasterXML / jackson-dataformat-xml

Extension for Jackson JSON processor that adds support for serializing POJOs as XML (and deserializing from XML) as an alternative to JSON

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

2.14 breaking change: parsing xml string as JsonNode/Object used to return just a String, now returns an Object/Map

jeronimonunes opened this issue · comments

Breaking change in my application when upgrading from 2.13.5 to 2.14

xmlMapper.readValue(xmlStreamReader, JsonNode.class)

with string "13,2" used to return "13,2". Now it returns a map {""="13,2"}

Same thing happens if I use xmlMapper.readValue(xmlStreamReader, Object.class)

I would need actual reproduction: string "13,2" is not valid XML so I'd need to know actual input in question.

I don't doubt there may be a change (this is likely for improved handling of JsonNode as target, to allow handling of duplicate elements), just need to know what exactly is being attempte.

    @Test
    void test() throws XMLStreamException, IOException {
        var factory = new WstxInputFactory();
        var stringReader = new StringReader("<d>13,2</d>");
        var xmlStreamReader = factory.createXMLStreamReader(stringReader);
        xmlStreamReader.nextTag();
        var jsonNode = xmlMapper.readValue(xmlStreamReader, JsonNode.class);
        assertEquals(TextNode.class,jsonNode.getClass());
    }
Expected :class com.fasterxml.jackson.databind.node.TextNode
Actual   :class com.fasterxml.jackson.databind.node.ObjectNode

Sorry, I should have written the whole xml in the description.
About the example above, same thing happens if I try to pass Object.class to readValue. It used to return a String, now it returns a Map.

Hmmh. Ok, I wrote first answer, saying this is expected... but then started thinking description was not correct.

What I do think is happening is that the change is due to improved handling of root level POJOs; and related to ambiguity of java.lang.Object as target; for which both Map and String are legal... and where with XML there is bit of natural ambiguity.

I suspect that the new behavior is what we will be going with, for what that is worth.

But I think that target type of String.class would give you the old behavior.

It does. I was first decoding everything to JsonNode and later using treeToValue to convert to other types.

Maybe Jackson can see that "" -> "ABC" is not a legal map because it only have "" as key and then return only the value?

I'm handling huge xmls and was keeping a temporary JsonNode before converting to the final type so I could log the content of that tag if the conversation failed. Do you know another temporary object I can use to store a single Xml tag for later conversion?

Empty String ("") is a valid JSON key.

Unfortunately buffering by Jackson uses TokenBuffer, which retains only converted JsonTokens, not the underlying XML contents.

I would have recommended trying JsonNode, but it probably has similar behavior.
I cannot think of anything that would safely buffer everything without transformation, unfortunately.

It may be necessary to do buffering at lower level (Reader or InputStream used), and use that for diagnostics on failure: JsonFactory (or XmlFactory subtype) has method

public JsonFactory setInputDecorator(InputDecorator d)

that may make this approach simpler (although if you control caller you can just wrap Reader / InputStream on your own).