Skip to content

Nulls.AS_EMPTY doesn't work for collections containing values without default constructor (like Records) #3084

Closed

Description

@krzyk

Describe the bug
When deserializating an empty JSON object {} into a record that contains a list of another record results in:

java.lang.IllegalStateException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot create empty instance of [collection type; class java.util.List, contains [simple type, class com.example.Test$Foo$Bar]], no default Creator
 at [Source: (String)"{}"; line: 1, column: 1]

Version information
2.12.2

To Reproduce

   record Foo(List<Bar> list) {

        record Bar(String name, String value) {}
    }

    @Test
    public void test() {
        ObjectMapper mapper = new ObjectMapper().setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
        try {
            mapper.readValue("{}", Foo.class);
        } catch (JsonProcessingException e) {
            throw new IllegalStateException(e);
        }
    }

The above fails with:

java.lang.IllegalStateException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot create empty instance of [collection type; class java.util.List, contains [simple type, class com.example.Test$Foo$Bar]], no default Creator
 at [Source: (String)"{}"; line: 1, column: 1]

Expected behavior
I would expect the deserialization give me an empty list.

Activity

  1. added
    to-evaluateIssue that has been received but not yet evaluated
    on Mar 19, 2021
  2. added
    RecordIssue related to JDK17 java.lang.Record support
    on Apr 11, 2021
  3. removed
    to-evaluateIssue that has been received but not yet evaluated
    on Jul 15, 2021
  4. sagansfault commented on May 24, 2022

    @sagansfault

    Any news on this? I recently just ran into the same issue

  5. yihtserns commented on Jan 9, 2023

    @yihtserns
    Contributor

    @krzyk maybe should be using .forValueNulls(Nulls.AS_EMPTY) instead of .forContentNulls(Nulls.AS_EMPTY)?

    Otherwise, can you please provide an example for JavaBeans (i.e. not Records) that actually works with .forContentNulls?

  6. cowtowncoder commented on Jan 11, 2023

    @cowtowncoder
    Member

    @yihtserns You are correct: content nulls are only for Map entries and array/Collection elements; not for POJO/Record properties.

    But the exception is strange at any rate: it should not be a problem to create empty List... (it gets mapped to ArrayList by default, uses default constructor).

  7. yihtserns commented on Jan 11, 2023

    @yihtserns
    Contributor

    But the exception is strange at any rate: it should not be a problem to create empty List...

    @cowtowncoder seems like it is complaining that Bar does not have no-arg constructor:

    simple type, class com.example.Test$Foo$Bar

    ...although the error message does sound misleading. Same behaviour can be observed when using an equivalent non-Records class:

    public static class Foo {
    
        private List<Bar> list;
    
        @JsonCreator
        public Foo(@JsonProperty("list") List<Bar> list) {
            this.list = list;
        }
    
        public static class Bar {
    
            private String name;
            private String value;
    
            @JsonCreator
            public Bar(@JsonProperty("name") String name, @JsonProperty("value") String value) {
                this.name = name;
                this.value = value;
            }
        }
    }
    

    The issue goes away by adding a no-arg constructor to Bar:

    public static class Bar {
    
        private String name;
        private String value;
    
        @JsonCreator
        public Bar(@JsonProperty("name") String name, @JsonProperty("value") String value) {
            this.name = name;
            this.value = value;
        }
    
        public Bar() { // No more issue with this
        }
    }
    

    Unfortunately, adding a no-arg constructor (with/without @JsonCreator) for the Bar record class won't fix the issue (although it can work on #3724's branch). UPDATE: Starting from 2.15 (due to #3724), adding no-arg constructor for the Bar record class will make the error go away.

  8. cowtowncoder commented on Jan 12, 2023

    @cowtowncoder
    Member

    Ah. Ok, so the issue here is specifically that due to setting that would use "As.EMPTY" for elements of List, and since nominal type of List property is one that does not have zero-args constructor, things fail.
    This because in the event we did need "empty" Bar instance we'd have no way to construct one.

    That is sort of valid reason to fail, potentially, if (but only if?) we ever needed to have empty Bar instance.
    Which here we don't.

    I think there's an older issue mentioning the same problem wrt (overly) eager construction of handler to provide "empty" instance. But there is also then the question of deferring failure to a later point -- is that always desireable?
    Sometimes it'd be good to know about potential problem during construction of deserializer and not wait until specific piece of data triggers the condition.

    For now it'd make sense to change configuration to use .forValueNulls(Nulls.AS_EMPTY), not .forContentNulls(...).
    Worth noting, too, is that @JsonSetter(...) annotation can be added to the property to override setting for List property as well.

  9. changed the title [-]Nulls.AS_EMPTY doesn't work for collections containing records[/-] [+]`Nulls.AS_EMPTY` doesn't work for collections containing values without default constructor (like Records)[/+] on Jan 16, 2023
  10. added a commit that references this issue on Feb 18, 2026
  11. added
    has-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issue
    on Feb 18, 2026
  12. added this to the 3.1.0 milestone on Feb 18, 2026
  13. added a commit that references this issue on Feb 18, 2026
    1f46815
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    RecordIssue related to JDK17 java.lang.Record supporthas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issue

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions