jackson-dataformat-xml icon indicating copy to clipboard operation
jackson-dataformat-xml copied to clipboard

Jackson fails to instantiate class when only text node is present

Open codemonstur opened this issue 1 year ago • 12 comments

The following code generates an exception:

public class JacksonBug {

    public static final String XML_WORKS_1 = """
            <root>
                <nested>
                    <other>text</other>
                    The text node.
                </nested>
            </root>
            """;
    public static final String XML_WORKS_2 = """
            <root>
                <plain>The text node.</plain>
            </root>
            """;
    public static final String XML_FAILS = """
            <root>
                <nested>The text node.</nested>
            </root>
            """;

    private static class Root {
        public Nested nested;
        public Plain plain;
    }
    private static class Nested {
        @JacksonXmlProperty(isAttribute = false)
        public String other;
        @JacksonXmlProperty(isAttribute = false)
        public String reallyNotHere;
        @JacksonXmlText
        public String text;
    }
    private static class Plain {
        @JacksonXmlText
        public String text;
    }

    public static void main(final String... args) throws JsonProcessingException {
        final var xmlMapper = new XmlMapper();
        xmlMapper.readValue(XML_WORKS_1, Root.class);
        xmlMapper.readValue(XML_WORKS_2, Root.class);
        xmlMapper.readValue(XML_FAILS, Root.class);
    }

}

Setting fields to private or public has no effect. If I add the tag the parsing works fine. If I remove the other and reallyNotHere fields the parsing works fine. But when the child tags are NOT there and the field IS there I get this Exception:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `tools.JacksonBug$Nested` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('The text node.')
 at [Source: (StringReader); line: 2, column: 27] (through reference chain: tools.JacksonBug$Root["nested"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1739)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1364)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:311)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1504)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:197)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
	at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
	at com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:91)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3772)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3740)
	at tools.JacksonBug.main(JacksonBug.java:50)

Process finished with exit code 1

Jackson version: 2.15.2

codemonstur avatar Sep 11 '23 09:09 codemonstur