Skip to content

Deserializing @JacksonXmlElementWrapper(useWrapping = false) fails on missing (optional) attribute #64

@nezda

Description

@nezda

Attempting to deserialize an unwrapped collection field (@JacksonXmlElementWrapper(useWrapping = false)) fails if element is missing an attribute. For example, given:

static class Optional {
    @JacksonXmlText
    public String number = "NOT SET";
    public String type = "NOT SET";
}
static class MultiOptional {
    @JacksonXmlElementWrapper(useWrapping = false)
    public List<Optional> optional;
}

XmlMapper can handle <MultiOptional><optional type='work'>123-456-7890</optional></MultiOptional>
but not <MultiOptional><optional>123-456-7890</optional></MultiOptional> (since it is missing type property).

Here are some related additions I made to com.fasterxml.jackson.dataformat.xml.failing.TestDeserialization to refine this issue:

        private static class StateAttrLocalName
    {
        @JacksonXmlProperty(localName="state", isAttribute=true)
        public String stateAttr = "NOT SET";

                @Override public String toString() { return "StateAttrLocalName: stateAttr: " + stateAttr; }
    }

        public void testAttrLocalName() throws Exception
    {
        StateAttrLocalName ob = MAPPER.readValue("<Wrapper state='stateAttr'></Wrapper>",
                StateAttrLocalName.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob);
        assertEquals("stateAttr", ob.stateAttr);
    }


        private static class StateAttr
    {
        @JacksonXmlProperty(localName="state", isAttribute=true)
        public String state = "NOT SET";

                @Override public String toString() { return "StateAttr: state: " + state; }
    }

        public void testAttr() throws Exception
    {
        StateAttr ob = MAPPER.readValue("<Wrapper state='stateAttr'></Wrapper>",
                StateAttr.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob);
        assertEquals("stateAttr", ob.state);
    }

        private static class TwoStates
    {
        @JacksonXmlProperty(localName="state", isAttribute=true)
        public String stateAttr = "NOT SET";
        public String state = "NOT SET";

                @Override public String toString() { return "TwoStates: stateAttr: " + stateAttr + " state: " + state; }
    }

    public void testAttrElementConflict() throws Exception
    {
        TwoStates ob = MAPPER.readValue("<Wrapper state='stateAttr'><state>stateElement</state></Wrapper>",
                TwoStates.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob);
        assertEquals("stateElement", ob.state);
        assertEquals("stateAttr", ob.stateAttr); // attribute stateAttr is ignored
    }

        private static class Optional
    {
                @JacksonXmlText
        public String number = "NOT SET";
        //@JacksonXmlProperty(isAttribute=true)
                public String type = "NOT SET";

                @Override public String toString() { return "Optional: number: " + number + " type: " + type; }
    }

    public void testOptionalAttr() throws Exception
    {
        Optional ob = MAPPER.readValue("<phone type='work'>123-456-7890</phone>",
                Optional.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob);
        assertEquals("123-456-7890", ob.number);
        assertEquals("work", ob.type);
    }

    public void testMissingOptionalAttr() throws Exception
    {
        Optional ob = MAPPER.readValue("<phone>123-456-7890</phone>",
                Optional.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob);
        assertEquals("123-456-7890", ob.number);
        assertEquals("NOT SET", ob.type);
    }

        private static class MultiOptional
    {
                @JacksonXmlElementWrapper(useWrapping = false)
                public List<Optional> optional;

                @Override public String toString() { return "MultiOptional: optional's: " + optional; }
    }

        public void testMultiOptional() throws Exception
    {
        MultiOptional ob = MAPPER.readValue("<MultiOptional><optional type='work'>123-456-7890</optional></MultiOptional>",
                MultiOptional.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob); // works fine
//        assertEquals("123-456-7890", ob.number);
//        assertEquals("NOT SET", ob.type);
    }

        public void testMultiOptionalWithMissingType() throws Exception
    {
            MultiOptional ob = MAPPER.readValue("<MultiOptional><optional>123-456-7890</optional></MultiOptional>",
                MultiOptional.class);
        assertNotNull(ob);
                System.err.println("ob: " + ob); // fails: 
//        assertEquals("123-456-7890", ob.number);
//        assertEquals("NOT SET", ob.type);
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions