From 4b13be926ed53a846c8154548d53f98ba9ac3e2e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Jun 2025 22:42:58 +0100 Subject: [PATCH 1/2] add config to allow override of deserializeNullCollectionsAsEmpty --- ...ainerDeserializerWithNullValueAsEmpty.java | 4 +++- .../jackson/module/scala/ScalaModule.scala | 11 +++++++++ .../deser/CaseClassDeserializerTest.scala | 23 ++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/module/scala/deser/ContainerDeserializerWithNullValueAsEmpty.java b/src/main/java/com/fasterxml/jackson/module/scala/deser/ContainerDeserializerWithNullValueAsEmpty.java index e223780e7..52c9aa37c 100644 --- a/src/main/java/com/fasterxml/jackson/module/scala/deser/ContainerDeserializerWithNullValueAsEmpty.java +++ b/src/main/java/com/fasterxml/jackson/module/scala/deser/ContainerDeserializerWithNullValueAsEmpty.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase; +import com.fasterxml.jackson.module.scala.ScalaModule; /** * Internal Usage only @@ -17,7 +18,8 @@ protected ContainerDeserializerWithNullValueAsEmpty(JavaType selfType) { @Override public T getNullValue(DeserializationContext ctxt) throws JsonMappingException { - if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { + if (!ScalaModule.shouldDeserializeNullCollectionsAsEmpty() || + ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { return super.getNullValue(ctxt); } else { return (T) getEmptyValue(ctxt); diff --git a/src/main/scala/com/fasterxml/jackson/module/scala/ScalaModule.scala b/src/main/scala/com/fasterxml/jackson/module/scala/ScalaModule.scala index d3a3fa3da..f00d557e6 100644 --- a/src/main/scala/com/fasterxml/jackson/module/scala/ScalaModule.scala +++ b/src/main/scala/com/fasterxml/jackson/module/scala/ScalaModule.scala @@ -49,6 +49,17 @@ object ScalaModule { } } + private var deserializeNullCollectionsAsEmpty = true + def builder(): Builder = new Builder() + + /** + * @return whether the module should support deserializing null collections as empty (default: true) + */ + def shouldDeserializeNullCollectionsAsEmpty(): Boolean = deserializeNullCollectionsAsEmpty + + def deserializeNullCollectionsAsEmpty(asEmpty: Boolean): Unit = { + deserializeNullCollectionsAsEmpty = asEmpty + } } diff --git a/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala b/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala index a6bd07500..9fd000de5 100644 --- a/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala +++ b/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala @@ -206,7 +206,18 @@ class CaseClassDeserializerTest extends DeserializerTest { result.list shouldBe List.empty } - it should "fail when deserializing null input for list if FAIL_ON_NULL_CREATOR_PROPERTIES enabled" in { + it should "deserialize list as null if deserializeNullCollectionsAsEmpty config is false" in { + val input = """{}""" + try { + ScalaModule.deserializeNullCollectionsAsEmpty(false) + val result = deserialize(input, classOf[ListHolder[String]]) + result.list shouldBe null + } finally { + ScalaModule.deserializeNullCollectionsAsEmpty(true) // reset to default + } + } + + it should "fail when deserializing null input for list if FAIL_ON_NULL_CREATOR_PROPERTIES enabled" in { val input = """{}""" val mapper = newBuilder.enable(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES).build() intercept[com.fasterxml.jackson.databind.exc.MismatchedInputException] { @@ -235,4 +246,14 @@ class CaseClassDeserializerTest extends DeserializerTest { } } + it should "deserialize map as null if deserializeNullCollectionsAsEmpty config is false" in { + val input = """{}""" + try { + ScalaModule.deserializeNullCollectionsAsEmpty(false) + val result = deserialize(input, classOf[MapHolder[Int, String]]) + result.map shouldBe null + } finally { + ScalaModule.deserializeNullCollectionsAsEmpty(true) // reset to default + } + } } From 5ab4fc4f507c01095865df32fec9fcea66d03a4c Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Jun 2025 22:46:24 +0100 Subject: [PATCH 2/2] Update CaseClassDeserializerTest.scala --- .../jackson/module/scala/deser/CaseClassDeserializerTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala b/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala index 9fd000de5..0503a234c 100644 --- a/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala +++ b/src/test/scala/com/fasterxml/jackson/module/scala/deser/CaseClassDeserializerTest.scala @@ -217,7 +217,7 @@ class CaseClassDeserializerTest extends DeserializerTest { } } - it should "fail when deserializing null input for list if FAIL_ON_NULL_CREATOR_PROPERTIES enabled" in { + it should "fail when deserializing null input for list if FAIL_ON_NULL_CREATOR_PROPERTIES enabled" in { val input = """{}""" val mapper = newBuilder.enable(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES).build() intercept[com.fasterxml.jackson.databind.exc.MismatchedInputException] {