jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

Unable to deserialize @JsonUnwrapped Optional<> field using Jackson

Open vbarhatov opened this issue 5 years ago • 4 comments

I tried to apply @JsonUnwrapped annotation to Optional<> field and can't figure out why deserialization turns this field into null value.

I wrote a test to demonstrate this issue and marked a place where the test fails: // throws java.lang.AssertionError

Tried this with jackson-databind:2.9.10.4 and jackson-databind:2.11.0 using corresponding version of jackson-datatype-jdk8. The result is the same.

public class JacksonTest {
    public static class Person {
        @JsonUnwrapped
        public MainData mainData;
        @JsonUnwrapped
        public Optional<AdditionalData> additionalData;
    }

    public static class MainData {
        public String name;
    }

    public static class AdditionalData {
        public String address;
    }

    @Test
    public void jsonUnwrappedWithOptionalTest() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jdk8Module());

        Person expected = new Person();
        expected.mainData = new MainData();
        expected.mainData.name = "Homer";
        expected.additionalData = Optional.of(new AdditionalData());
        expected.additionalData.get().address = "Springfield";

        String json = mapper.writeValueAsString(expected);

        assertThat(json, is("{\"name\":\"Homer\",\"address\":\"Springfield\"}"));

        Person actual = mapper.readValue(json, Person.class);

        assertNotNull(actual.mainData);
        assertThat(actual.mainData.name, is("Homer"));
        assertNotNull(actual.additionalData); // throws java.lang.AssertionError; actual.additionalData is null
        assertThat(actual.additionalData.isPresent(), is(true));
        assertThat(actual.additionalData.get().address, is("Springfield"));
    }
}

It looks like a bug. Isn't it?

WORKAROUND: Finally, I added a custom deserializer using @JsonDeserialize as a workaround but I would like to find a right solution.

vbarhatov avatar May 26 '20 12:05 vbarhatov