question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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

See original GitHub issue

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!

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Dec 13, 2021

Ok it took bit longer (apologies, I have been bit burnt out, but now regaining my energy for some OSS work 😃 ) but I did merge suggested fix. It will go in 2.12.6 and 2.13.1 releases.

It does look, from above, that there is at least one remaining problem (failure on 2.11 and 2.12), so it’d make sense to file a follow up issue with that test; I will consider this one just for the regression part which is most critical to fix first. If someone could file that issue that’d be great: can just link to still failing test, this issue as background.

Thank you @daniel-kr for reporting this, @lglauer for contributing the fix!

1reaction
cowtowncodercommented, Nov 23, 2021

Unfortunately I have had very little time to spend on Jackson for past couple of months, so this fell through the cracks. I will add this on my TODO list to investigate – I don’t want to give you an answer before doing that. I hope to have a look some time this week.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Each list element is wrapped into an extra tag with the name of ...
I used the XJC compiler to create schematically compliant Java classes. Now I have the problem, that the object mapper does wrap list ......
Read more >
Deserializing Polymorphic Types with @JsonUnwrapped ...
My SinglePolyUnwrappedDeserializer from this Gist can handle a single polymorphic @JsonUnwrapped property. It's in Kotlin, but can easily be ported to Java ...
Read more >
FasterXML - Bountysource
A @JsonUnwrapped with a @JacksonXmlElementWrapper(useWrapping=false) on a collection fails reading from XML, but not JSON $ 0. Created 4 years ago in FasterXML/ ......
Read more >
Using @JsonTypeInfo annotation to handle polymorphic types
In cases where polymorphic types are persisted to JSON, there's no way for Jackson to figure out the right type during deserialization.
Read more >
Jackson API beyond ObjectMapper - Medium
One big challenge for using ObjectMapper is its thread-safety: if (and only ... defaultUseWrapper(false) // use "unwrapped" Lists in XML
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found