Skip to content

Problem when using defaultUseWrapper(false) in combination with polymorphic typesΒ #490

@daniel-kr

Description

@daniel-kr

Hello,

we are currently trying to upgrade jackson-dataformat-xml in our product from 2.11.4 to 2.12.4.
However, with the new version we encounter problems when it comes to using defaultUseWrapper(false) in combination with polymorphic types.

Given the following interface and concrete implementation:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = MyType.class, name = "myType"),
})
public interface IMyType {
}
public class MyType implements IMyType {

    @JsonCreator
    public MyType(
            @JsonProperty("stringValue") String stringValue,
            @JsonProperty("typeNames") Collection<String> typeNames) {
        this.stringValue = stringValue;
        this.typeNames = typeNames;
    }

    public final String stringValue;
    public final Collection<String> typeNames;

    // equals() and hashcode() removed from the snippet
}

Now doing a roundtrip serialization using the following code:

public class Main {

    public static void main(String[] args) throws JsonProcessingException {
        XmlMapper xmlMapper = XmlMapper.builder()
                //.configure(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL, true)
                //.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
                .defaultUseWrapper(false).build();

        MyType myType = new MyType("hello", List.of("type1", "type2"));

        String stringValue = xmlMapper.writeValueAsString(myType);
        System.out.println(stringValue);
        IMyType outputType = xmlMapper.readValue(stringValue, IMyType.class);
        Preconditions.checkState(myType.equals(outputType));
    }
}

While this works great on version 2.11.4, it produces the following exception during de-serialization on 2.12.4:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `java.util.ArrayList` (although at least one Creator exists): no String-argument constructor/factory method to de-serialize from String value ('type1')

The produced XML looks as follows on both versions:

<MyType type="myType">
    <stringValue>hello</stringValue>
    <typeNames>type1</typeNames>
    <typeNames>type2</typeNames>
</MyType>

During the tests we recognized the following behavior:

  • Using the concrete type MyType instead of the interface IMyType in the call to readValue works on both versions.
  • Removing the additional attribute stringValue and leaving just the collection attribute leads to an exception on 2.11.4 as well, but a slightly different one.
  • Using defaultUseWrapper(true) works on both versions. Unfortunately, this is not an option in our case since it changes the XML format and we need to be backwards compatible.
  • Option EMPTY_ELEMENT_AS_NULL does not have any influence on the mentioned behavior.
  • Option ACCEPT_SINGLE_VALUE_AS_ARRAY prevents the exception but de-serializes only the last element of the collection.

I uploaded the example to GitHub:

Thanks in advance!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions