diff --git a/pom.xml b/pom.xml
index 3844ea014..aa02b5b35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
com.fasterxml.jackson
jackson-base
- 2.13.0-rc2-SNAPSHOT
+ 2.13.0-SNAPSHOT
com.fasterxml.jackson.module
jackson-module-kotlin
diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x
index ff253804e..629e1f913 100644
--- a/release-notes/CREDITS-2.x
+++ b/release-notes/CREDITS-2.x
@@ -32,6 +32,10 @@ wrongwrong (k163377@github)
* Contributed #438: Fixed mapping failure when `private` `companion object` is named
(2.13)
+Dmitri Domanine (novtor@github)
+* Contributed fix for #490: Missing value of type JsonNode? is deserialized as NullNode instead of null
+ (2.13)
+
Marshall Pierce (marshallpierce@github)
* #474: Reported disrespect for @JsonProperty on parent class
(2.12.NEXT)
diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt
index aed1ee847..2196d9687 100644
--- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt
+++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt
@@ -101,8 +101,13 @@ internal class KotlinValueInstantiator(
}
tempParamVal
} else {
- // trying to get suitable "missing" value provided by deserializer
- jsonProp.valueDeserializer?.getNullValue(ctxt)
+ if(paramDef.type.isMarkedNullable) {
+ // do not try to create any object if it is nullable and the value is missing
+ null
+ } else {
+ // to get suitable "missing" value provided by deserializer
+ jsonProp.valueDeserializer?.getAbsentValue(ctxt)
+ }
}
if (paramVal == null && ((nullToEmptyCollection && jsonProp.type.isCollectionLikeType) || (nullToEmptyMap && jsonProp.type.isMapLikeType))) {
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github490.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github490.kt
new file mode 100644
index 000000000..38fe26109
--- /dev/null
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github490.kt
@@ -0,0 +1,81 @@
+package com.fasterxml.jackson.module.kotlin.test.github
+
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.node.NullNode
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.fasterxml.jackson.module.kotlin.readValue
+import org.hamcrest.CoreMatchers
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Test
+
+class TestGithub490 {
+ val mapper = jacksonObjectMapper()
+ val value: DataClassWithAllNullableParams = mapper.readValue(
+ "{" +
+ "\"jsonNodeValueWithNullAsDefaultProvidedNull\":null, " +
+ "\"jsonNodeValueProvidedNull\":null}"
+ )
+
+ @Test
+ fun testKotlinDeserialization_intValue() {
+ assertThat(
+ "Nullable missing Int value should be deserialized as null",
+ value.intValue,
+ CoreMatchers.nullValue()
+ )
+ }
+
+ @Test
+ fun testKotlinDeserialization_stringValue() {
+ assertThat(
+ "Nullable missing String value should be deserialized as null",
+ value.stringValue,
+ CoreMatchers.nullValue()
+ )
+ }
+
+ @Test
+ fun testKotlinDeserialization_jsonNodeValue() {
+ assertThat(
+ "Nullable missing JsonNode value should be deserialized as null and not as NullNode",
+ value.jsonNodeValue,
+ CoreMatchers.nullValue()
+ )
+ }
+
+ @Test
+ fun testKotlinDeserialization_jsonNodeValueProvidedNull() {
+ assertThat(
+ "Nullable JsonNode value provided as null should be deserialized as NullNode",
+ value.jsonNodeValueProvidedNull,
+ CoreMatchers.equalTo(NullNode.instance)
+ )
+ }
+
+ @Test
+ fun testKotlinDeserialization_jsonNodeValueWithNullAsDefault() {
+ assertThat(
+ "Nullable by default missing JsonNode value should be deserialized as null and not as NullNode",
+ value.jsonNodeValueWithNullAsDefault,
+ CoreMatchers.nullValue()
+ )
+ }
+
+ @Test
+ fun testKotlinDeserialization_jsonNodeValueWithNullAsDefaultProvidedNull() {
+ assertThat(
+ "Nullable by default JsonNode with provided null value in payload should be deserialized as NullNode",
+ value.jsonNodeValueWithNullAsDefaultProvidedNull,
+ CoreMatchers.equalTo(NullNode.instance)
+ )
+ }
+}
+
+data class DataClassWithAllNullableParams(
+ val intValue: Int?,
+ val stringValue: String?,
+ val jsonNodeValue: JsonNode?,
+ val jsonNodeValueProvidedNull: JsonNode?,
+ val jsonNodeValueWithNullAsDefault: JsonNode? = null,
+ val jsonNodeValueWithNullAsDefaultProvidedNull: JsonNode? = null
+)