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

Disabling FAIL_ON_INVALID_SUBTYPE breaks polymorphic deserialization of Enums #2775

Closed
holgerknoche opened this issue Jun 24, 2020 · 4 comments
Milestone

Comments

@holgerknoche
Copy link

Apparently, disabling the FAIL_ON_INVALID_SUBTYPE feature has some (at least for me) unexpected side-effects on the deserialization of enums. I originally found this issue in jackson-databind 2.10.0, but it still exists in 2.11.0.
I have an enum that implements an interface:

@JsonTypeInfo(use = Id.NAME)
public interface CustomEnum {}

@JsonTypeName("Test")
public enum TestEnum implements CustomEnum {
    VALUE;
}

Then, this test case works fine:

ObjectMapper mapper = new ObjectMapper();
mapper.registerSubtypes(TestEnum.class);
	
mapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
	
CustomEnum testValue = TestEnum.VALUE;
String json = mapper.writeValueAsString(testValue);
	
CustomEnum deserializedValue = mapper.readValue(json, CustomEnum.class);
assertEquals(testValue, deserializedValue);

However, when I disable the feature, the test case fails because deserializedValue is suddenly null. The reason seems to be that a NullyfingDeserializer is returned from TypeDeserializerBase._findDefaultImplDeserializer(...) instead of null. Therefore, the AsPropertyDeserializer no longer tries to read the value itself.

@cowtowncoder cowtowncoder added good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project hacktoberfest Issue related to Hactoberfest activities, eligible for additional rewards labels Oct 9, 2020
@singleton11
Copy link

singleton11 commented Oct 11, 2020

public class Test {

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
    interface CustomEnum {}

    @JsonTypeName("Test")
    enum TestEnum implements CustomEnum {
        VALUE;
    }

    @org.junit.Test
    public void test() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerSubtypes(TestEnum.class);

//        mapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);

        CustomEnum testValue = TestEnum.VALUE;
        String json = mapper.writeValueAsString(testValue);

        CustomEnum deserializedValue = mapper.readValue(json, CustomEnum.class);
        assertEquals(testValue, deserializedValue);
    }
}

This test works fine in 2.11 branch, what I do wrong?

UPD: Sorry, I see, I just had to explicitly disable this feature

@cowtowncoder
Copy link
Member

Interesting. I can reproduce this. Workaround that trips handling appears to be fix for #148 so can not just remove use of NullifyingDeserializer.

@cowtowncoder
Copy link
Member

Fundamentally the problem is that Enums are serialized as Strings -- scalar value -- and not as JSON Objects, so it is not possible use inclusion of As.PROPERTY. Instead, serialization occurs using As.WRAPPER_ARRAY.
But on deserialization this can not be determined. I am not sure why it appears to work with different settings however.

A solution here really is to use different inclusion:

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_ARRAY)

and things will work.

It is odd that without disabling FAIL_ON_INVALID_SUBTYPE things appear to work ok, so I'll see if there is a way to handle this case as expected. But in the mean time specifying more general inclusion type (WRAPPER_ARRAY is guaranteed to work all shapes, ditto for WRAPPER_OBJECT).

cowtowncoder added a commit that referenced this issue Oct 14, 2020
@cowtowncoder cowtowncoder added 2.12 and removed good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project hacktoberfest Issue related to Hactoberfest activities, eligible for additional rewards 2.11 labels Oct 14, 2020
@cowtowncoder cowtowncoder changed the title Disabling FAIL_ON_INVALID_SUBTYPE breaks enum deserialization with interfaces Disabling FAIL_ON_INVALID_SUBTYPE breaks polymorphic deserialization of Enums Oct 14, 2020
@cowtowncoder cowtowncoder added this to the 2.12.0-rc2 milestone Oct 14, 2020
@cowtowncoder
Copy link
Member

I was able to fix this, but since there is some risk in fix will only add in for 2.12.0 (probably in 2.12.0-rc2), not for earlier minor versions. I suspect risk simply because this affects edge cases and testing is probably not extensive for such cases.

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