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
Apache License 2.0
561 stars 221 forks source link

Disabling wrapper on list (e.g. defaultUseWrapper = false) does not serialize/deserialize null lists as expected #627

Open vtarchon opened 5 months ago

vtarchon commented 5 months ago

I noticed that when i serialize an object with a null list and disable using a default wrapper around lists, upon deserialization the object returned differs from the object serialized.

Here is a test of the problem

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.io.IOException;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class JacksonTest {

    @Test
    public void test() throws IOException {
        XmlMapper mapper = XmlMapper.builder().defaultUseWrapper(false).build();

        Parent a = new Parent();
        String out = mapper.writeValueAsString(a);
        Parent b = mapper.readValue(out, Parent.class);
        Assertions.assertEquals(a.getChildren(), b.getChildren());
    }

    @JacksonXmlRootElement
    static class Parent {
        List<Child> children;

        public Parent() {}

        public List<Child> getChildren() {
            return children;
        }

        public void setChildren(List<Child> children) {
            this.children = children;
        }
    }

    static class Child {
        private String name;
    }
}

class Parent has a list of class Child that is null, when this object is serialized the following xml is

<Parent><children/></Parent>

if you take this xml and deserialize it back into a Parent object what ends up happening is that the children property is a list that has one element, an object of Child with null properties. I was expecting that Parent would have a null list instead.

If you enable wrapper, it works fine and the serialized xml is

<Parent/>

which deserializes into the same object as the original

vtarchon commented 5 months ago

it looks like if the array is initialized to an empty array or if i add @JsonInclude(JsonInclude.Include.NON_EMPTY) to the class, it'll serialized without the empty element when the wrapper is disabled.

cowtowncoder commented 5 months ago

I think there is unfortunately ambiguity wrt XML with default settings, for this case. But enabling ToXmlGenerator.Feature.WRITE_NULLS_AS_XSI_NIL should help preserve null as null -- this settings is disabled by default for backwards-compatibility reasons (added in 2.10).