Nulls.AS_EMPTY doesn't work for collections containing values without default constructor (like Records) #3084
Copy link
Copy link
Closed
Labels
RecordIssue related to JDK17 java.lang.Record supportIssue related to JDK17 java.lang.Record supporthas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issueIndicates that there exists a test case (under `failing/`) to reproduce the issue
Milestone
Description
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.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
RecordIssue related to JDK17 java.lang.Record supportIssue related to JDK17 java.lang.Record supporthas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issueIndicates that there exists a test case (under `failing/`) to reproduce the issue
Activity
sagansfault commentedon May 24, 2022
Any news on this? I recently just ran into the same issue
yihtserns commentedon Jan 9, 2023
@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?cowtowncoder commentedon Jan 11, 2023
@yihtserns You are correct: content nulls are only for
Mapentries and array/Collectionelements; 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 toArrayListby default, uses default constructor).yihtserns commentedon Jan 11, 2023
@cowtowncoder seems like it is complaining that
Bardoes not have no-arg constructor:...although the error message does sound misleading. Same behaviour can be observed when using an equivalent non-Records class:
The issue goes away by adding a no-arg constructor to
Bar:Unfortunately, adding a no-arg constructor (with/withoutUPDATE: Starting from@JsonCreator) for theBarrecord class won't fix the issue (although it can work on #3724's branch).2.15(due to #3724), adding no-arg constructor for theBarrecord class will make the error go away.cowtowncoder commentedon Jan 12, 2023
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 ofListproperty is one that does not have zero-args constructor, things fail.This because in the event we did need "empty"
Barinstance 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
Barinstance.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 forListproperty as well.[-]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)[/+]Add failing test for #3084
Add failing test for #3084 (#5696)
Fix #3084
Fix FasterXML#3084 (FasterXML#5697)