FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
399 stars 116 forks source link

@JsonCreator change the behaviour of Optional<> #233

Closed patryk-beekeeper closed 1 year ago

patryk-beekeeper commented 2 years ago

Describe the bug I have a use case when lack of field in json has different meaning than setting this field to null. To model this I use Optional<>. It works fine without @JsonCreator, but do not work with @JsonCreator

Version information 2.12.4

To Reproduce

class WithoutJsonCreator {
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public Optional<String> test;
}

class WithJsonCreator {
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public Optional<String> test;

    @JsonCreator
    public WithJsonCreator(@JsonProperty("test") Optional<String> test) {
        this.test = test;
    }
}

  @Test
  void shouldWorkWithAndWithoutJsonCreator() throws JsonProcessingException {
      String json = "[{},{\"test\":null}]";
      ObjectMapper objectMapper = new ObjectMapper().registerModule(new Jdk8Module());
      List<WithoutJsonCreator> without =  objectMapper.readValue(json, new TypeReference<>() {});

      assertNull(without.get(0).test);
      assertEquals(Optional.empty(), without.get(1).test);
      assertEquals(json, mapper.writeValueAsString(without));

      List<WithJsonCreator> with =  objectMapper.readValue(json, new TypeReference<>() {});

      System.out.println(with.get(0).test); // Optional.empty
      System.out.println(with.get(1).test); // Optional.empty
      assertEquals(json, mapper.writeValueAsString(with)); // FAIL: expected: <[{},{"test":null}]> but was: <[{"test":null},{"test":null}]>
  }

Expected behavior The behaviour for both classes should be the same and test should pass.

cowtowncoder commented 2 years ago

Since Optional handling provided by Java 8 module, transferring there.

cowtowncoder commented 1 year ago

This is a limitation -- only Creator-passed values can detect absence of value; for fields and setters nothing is done if no input is found. So the behavior is different but that is not considered a bug nor can be easily fixed. There may be an issue for jackson-databind to support handling of "absent" values for Fields and Methods (there is one for enforcing "required"-ness, and if that was done, "absent" aspect could also be supported.

Closing here, however, since this is not really specific to Optional nor can be solved here.