diff --git a/src/main/java/tools/jackson/databind/introspect/AnnotatedMethod.java b/src/main/java/tools/jackson/databind/introspect/AnnotatedMethod.java index 4997a1cf4a..d7740beaca 100644 --- a/src/main/java/tools/jackson/databind/introspect/AnnotatedMethod.java +++ b/src/main/java/tools/jackson/databind/introspect/AnnotatedMethod.java @@ -107,8 +107,7 @@ public final Object call(Object[] args) throws Exception { @Override public final Object call1(Object arg) throws Exception { try { - Object ret = _invokerUnary.get().invokeExact(arg); - return ret == null ? arg : ret; + return _invokerUnary.get().invokeExact(arg); } catch (final Throwable e) { throw sneakyThrow(e); } diff --git a/src/test/java/tools/jackson/databind/deser/creators/JsonCreatorReturningNull4938Test.java b/src/test/java/tools/jackson/databind/deser/creators/JsonCreatorReturningNull4938Test.java index d6a87fb9c5..c45b8d79b3 100644 --- a/src/test/java/tools/jackson/databind/deser/creators/JsonCreatorReturningNull4938Test.java +++ b/src/test/java/tools/jackson/databind/deser/creators/JsonCreatorReturningNull4938Test.java @@ -13,9 +13,11 @@ import static org.junit.jupiter.api.Assertions.*; // [databind#4938] Allow JsonCreator factory method to return `null` +// [databind#5401] Do not replace null from JsonCreator factory method public class JsonCreatorReturningNull4938Test extends DatabindTestUtil { + // [databind#4938] static class Localized3 { public final String en; public final String de; @@ -89,12 +91,32 @@ public void addProperty(String key, Object value) { } } + // [databind#5401] + static class NonEmpty5401 { + public NonEmptyString5401 nonEmpty; + } + + static class NonEmptyString5401 { + public final String value; + + @JsonCreator + public static NonEmptyString5401 of(String value) { + if (value == null || value.isEmpty()) { + return null; + } + return new NonEmptyString5401(value); + } + + private NonEmptyString5401(String value) { + this.value = value; + } + } private final ObjectMapper MAPPER = newJsonMapper(); + // [databind#4938] @Test void testDeserializeToNullWhenAllPropertiesAreNull() - throws Exception { Localized3 result = MAPPER.readValue( "{ \"en\": null, \"de\": null, \"fr\": null }", @@ -105,7 +127,6 @@ void testDeserializeToNullWhenAllPropertiesAreNull() @Test void testDeserializeToNonNullWhenAnyPropertyIsNonNull() - throws Exception { Localized3 result = MAPPER.readValue( "{ \"en\": \"Hello\", \"de\": null, \"fr\": null }", @@ -117,7 +138,6 @@ void testDeserializeToNonNullWhenAnyPropertyIsNonNull() @Test void testDeserializeReadingAfterCreatorProps() - throws Exception { // Should all fail... ObjectReader enabled = MAPPER.readerFor(Localized4.class) @@ -135,7 +155,6 @@ void testDeserializeReadingAfterCreatorProps() // Test to verify we are reading till the end of the OBJECT @Test void testDeserializeReadingUntilEndObject() - throws Exception { // Should all fail... ObjectReader enabled = MAPPER.readerFor(Localized4.class) @@ -156,7 +175,6 @@ void testDeserializeReadingUntilEndObject() @Test void testJsonCreatorNullWithAnySetter() - throws Exception { String JSON = "{ \"en\": null, \"de\": null, \"fr\": null, " + // These two properties are unknown @@ -166,4 +184,16 @@ void testJsonCreatorNullWithAnySetter() .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .readValue(JSON); } + + // [databind#5401] + @Test + void deserializeFieldToNullIfDelegatingCreatorReturnsNull() + { + NonEmpty5401 result = MAPPER.readValue( + "{ \"nonEmpty\": \"\" }", + NonEmpty5401.class); + + assertNotNull(result); + assertNull(result.nonEmpty); + } }