Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMLMapper fails to deserialize null (POJO reference) from blank tag #318

Closed
joschi opened this issue Oct 25, 2018 · 4 comments
Closed

XMLMapper fails to deserialize null (POJO reference) from blank tag #318

joschi opened this issue Oct 25, 2018 · 4 comments
Milestone

Comments

@joschi
Copy link

joschi commented Oct 25, 2018

I'm using XmlMapper to deserialize XML documents from some external sources and map them to predefined POJOs.

When Jackson encounters a blank tag (not empty, but only whitespace characters), I would expect it to deserialize it into a null reference or an equivalent empty collection, depending on the configuration of the XmlMapper.

Unfortunately, Jackson fails with a MismatchedInputException. Enabling DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT on the XmlMapper doesn't help either.

Is there a configuration flag which would make XmlWrapper interpret the blank tag as empty and deserialize it into null?

Jackson version: 2.9.7

Test case for reproduction:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;

public class DescriptionTest {
    private final XmlMapper mapper = new XmlMapper();

    @Test
    public void emptyString() throws IOException {
        String s = "<wrapper>"
                + "  <id>id</id>"
                + "  <nested></nested>"
                + "</wrapper>";

        Wrapper value = mapper.readValue(s, Wrapper.class);
        Assert.assertEquals("id", value.id);
        Assert.assertNull(value.nested);
    }

    @Test
    public void blankString() throws IOException {
        String s = "<wrapper>"
                + "  <id>id</id>"
                + "  <nested>    </nested>"
                + "</wrapper>";

        // This fails with the following exception:
        // com.fasterxml.jackson.databind.exc.MismatchedInputException:
        // Cannot construct instance of `JacksonXMLTest$Nested` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('    ')
        Wrapper value = mapper.readValue(s, Wrapper.class);
        Assert.assertEquals("id", value.id);
        Assert.assertNull(value.nested);
    }

    @Test
    public void blankString2() throws IOException {
        String s = "<wrapper>"
                + "  <id>id</id>"
                + "  <nested>    </nested>"
                + "</wrapper>";

        // This fails with the following exception:
        // com.fasterxml.jackson.databind.exc.MismatchedInputException:
        // Cannot construct instance of `JacksonXMLTest$Nested` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('    ')
        ObjectMapper mapperCopy = mapper.copy().enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        Wrapper value = mapperCopy.readValue(s, Wrapper.class);
        Assert.assertEquals("id", value.id);
        Assert.assertNull(value.nested);
    }

    @Test
    public void missing() throws IOException {
        String s = "<wrapper>"
                + "  <id>id</id>"
                + "</wrapper>";

        Wrapper value = mapper.readValue(s, Wrapper.class);
        Assert.assertEquals("id", value.id);
        Assert.assertNull(value.nested);
    }

    @Test
    public void validStructure() throws IOException {
        String s = "<wrapper>"
                + "  <id>id</id>"
                + "  <nested>"
                + "    <nested2 attr=\"test\"><![CDATA[Some text]]></nested2>"
                + "  </nested>"
                + "</wrapper>";

        Wrapper value = mapper.readValue(s, Wrapper.class);
        Assert.assertEquals("id", value.id);
        Assert.assertEquals("test", value.nested.nested2.attr);
        Assert.assertEquals("Some text", value.nested.nested2.value);
    }


    static class Wrapper {
        @JacksonXmlProperty(localName = "id")
        String id;
        @JacksonXmlProperty(localName = "nested")
        Nested nested;
    }

    static class Nested {
        @JacksonXmlProperty(localName = "nested2")
        Nested2 nested2;
    }

    static class Nested2 {
        @JacksonXmlProperty(localName = "attr", isAttribute = true)
        String attr;
        @JacksonXmlText
        String value;
    }
}
@LakshmiSrinivas10101
Copy link

I am also facing the same issue. Could anyone provide your inputs?

@cowtowncoder
Copy link
Member

Yes, I can reproduce this. Added failing test. Would be good to resolve, but depends on whether I have time to look into this issue in near future.

@KonovalovaKV
Copy link

Any news?

@cowtowncoder
Copy link
Member

Figure out a way to do this, using ValueInstantiator; will go in 2.12.0 (since there is a possibility it would collide with something else).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants