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

ConfigOverride using Nulls.AS_EMPTY does not work with JsonManagedReference

Open robrat opened this issue 1 year ago • 3 comments

Search before asking

  • [X] I searched in the issues and found nothing similar.

Describe the bug

configOverride for Lists work as expected, but if any of the lists is a ManagedReference, then the list is initialized with null instead of an empty list.

Version Information

2.17.1

Reproduction

Without JsonManagedReference and JsonBackReference the children list is initialized with a non null value, but with these annotations it becomes null, but only after I add Value.forContentNulls, otherwise it would throw an IllegalStateException.

class JacksonManagedRefTest {

  @lombok.Getter @lombok.Setter
  static class Parent {
    private String name;

    @JsonManagedReference
    private List<Item> children = new ArrayList<>();
  }

  @lombok.Getter @lombok.Setter
  static class Item {
    private String name;

    @JsonBackReference
    private Parent parent;
  }

  @Test
  void test_nonEmptyChildren() throws Exception {
    ObjectMapper om = new ObjectMapper();

    String str = "{ \"name\": \"parent\", \"children\":[{\"name\":\"child1\"},{\"name\":\"child1\"}]}";
    Parent obj = om.readValue(str, Parent.class);
    Assertions.assertNotNull(obj.children);
  }

  // java.lang.IllegalStateException: Should never try to reset delegate
  @Test
  void test_nullChildren() throws Exception {
    ObjectMapper om = new ObjectMapper();
    om.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));

    String str = "{ \"name\": \"parent\", \"children\": null }";
    Parent obj = om.readValue(str, Parent.class);
    Assertions.assertNotNull(obj.children);
  }

  // not null assertion fails
  @Test
  void test_nullChildren_contentNullConfig() throws Exception {
    ObjectMapper om = new ObjectMapper();
    om.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
    om.configOverride(List.class).setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));

    String str = "{ \"name\": \"parent\", \"children\": null }";
    Parent obj = om.readValue(str, Parent.class);
    Assertions.assertNotNull(obj.children);
  }
}

Expected behavior

List property children is initialized with an empty list

Additional context

No response

robrat avatar Oct 21 '24 17:10 robrat

Quick note: first of all; thank you for reporting the issue and providing a test case.

Unfortunately we would need a reproduction that does not use Lombok, since project cannot add a Lombok dependency (even for tests).

Removing Lombok use could use verify that this problem is not due to Lombok processing (which is possible if not probably root cause).

cowtowncoder avatar Oct 27 '24 17:10 cowtowncoder

Also: while I don't think there is difference, trying with 2.18.0 would be good, to ensure issue has not been resolved in the latest minor version upgrade.

cowtowncoder avatar Oct 27 '24 17:10 cowtowncoder

I mostly used lombok to get a shorter unit test without the getter/setter noise. I removed lombok and also tried jackson 2.18, but without success. I pushed the change as a separate repo: https://github.com/robrat/jackson-nullasempty

robrat avatar Oct 28 '24 10:10 robrat