Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
daniel-kr opened this issue Aug 25, 2021 · 9 comments
Milestone

Comments

@daniel-kr
Copy link

daniel-kr commented Aug 25, 2021

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!

@daniel-kr
Copy link
Author

I tried with the recent patch release 2.12.5. The mentioned behavior still occurs on that release as well. 🙁

@lglauer
Copy link

lglauer commented Sep 21, 2021

I found that the commit d9738d92 introduced a regression that results in this issue.
By calling ((FromXmlParser) p).addVirtualWrapping(_namesToWrap, _caseInsensitive); only conditionally namesToWrap are not set as expected. This results in _parsingContext.shouldWrap returning false here.

@cowtowncoder A fix might be as easy as this: lglauer@48d0b81 , do you think this is a proper solution?

@daniel-kr
Copy link
Author

@cowtowncoder Please tell us if you consider this as a bug that is going to be fixed in the future (e.g. by applying our proposed pull request) or if it is something that we did wrong. This information would help us a lot in order to decide whether we should just wait or fork the project and apply the fix to the fork. At the moment this blocks us from using a recent version of jackson. Sooner or later it will become incompatible with other libraries. Therefore we need a solution. Thanks in advance!

@cowtowncoder
Copy link
Member

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.

@daniel-kr
Copy link
Author

Thank you very much! 🙂

@cowtowncoder cowtowncoder added this to the 2.12.6 milestone Dec 13, 2021
cowtowncoder added a commit that referenced this issue Dec 13, 2021
@cowtowncoder
Copy link
Member

cowtowncoder commented 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!

@daniel-kr
Copy link
Author

Thank you! 🙂

@daniel-kr
Copy link
Author

Hey! I think we can close this issue. Problem is solved in recent versions. Thanks again!

@cowtowncoder
Copy link
Member

Yes, was included in 2.12.6 but seems I forgot to close the issue. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants