diff --git a/pom.xml b/pom.xml
index 7001baf4..56c802e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -254,6 +254,12 @@
com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
+
+ com.fasterxml.jackson.module.kotlin.KotlinInstantiators#KotlinInstantiators(com.fasterxml.jackson.module.kotlin.ReflectionCache,boolean,boolean,boolean,boolean)
+
+
+ com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator#KotlinValueInstantiator(com.fasterxml.jackson.databind.deser.std.StdValueInstantiator,com.fasterxml.jackson.module.kotlin.ReflectionCache,boolean,boolean,boolean,boolean)
+
diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x
index 18e27f04..80485b08 100644
--- a/release-notes/CREDITS-2.x
+++ b/release-notes/CREDITS-2.x
@@ -18,6 +18,7 @@ Contributors:
# 2.21.0 (not yet released)
WrongWrong (@k163377)
+* #1042: Remove old StrictNullChecks
* #1041: Remove MissingKotlinParameterException
* #1039: Update settings for 2.20
diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index eaa01fe7..168a2abe 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -18,6 +18,8 @@ Co-maintainers:
2.21.0 (not yet released)
+#1042: The old StrictNullChecks backend has been removed.
+ This improves the throughput of deserialization slightly.
#1041: The deprecated MissingKotlinParameterException has been removed.
#1039: Kotlin has been upgraded to 2.1.x.
diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinFeature.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinFeature.kt
index 1e9a62a9..6ed9f16b 100644
--- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinFeature.kt
+++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinFeature.kt
@@ -40,13 +40,12 @@ enum class KotlinFeature(internal val enabledByDefault: Boolean) {
*
* With this disabled, the default, collections which are typed to disallow null members (e.g. `List`)
* may contain null values after deserialization.
- * Enabling it protects against this but has significant performance impact.
+ * Enabling this will cause an [InvalidNullException] to be thrown if null is entered.
+ *
+ * Internally, it will be the same as if [JsonSetter] (contentNulls = FAIL) had been granted.
+ *
+ * Benchmarks show that it can check for illegal nulls with throughput nearly identical to the default (see [jackson-module-kotlin#719]).
*/
- @Deprecated(
- level = DeprecationLevel.ERROR,
- message = "This option will be migrated to the new backend in 2.21.",
- replaceWith = ReplaceWith("NewStrictNullChecks")
- )
StrictNullChecks(enabledByDefault = false),
/**
@@ -80,15 +79,15 @@ enum class KotlinFeature(internal val enabledByDefault: Boolean) {
* Internally, it will be the same as if [JsonSetter] (contentNulls = FAIL) had been granted.
* Benchmarks show that it can check for illegal nulls with throughput nearly identical to the default (see [jackson-module-kotlin#719]).
*
- * Note that in the new backend, the exception thrown has changed from [MissingKotlinParameterException] to [InvalidNullException].
- * The message will be changed accordingly.
- * Since 2.19, the base class of [MissingKotlinParameterException] has also been changed to [InvalidNullException],
- * so be careful when catching it.
- *
* This is a temporary option for a phased backend migration,
* which will eventually be merged into [StrictNullChecks].
* Also, specifying both this and [StrictNullChecks] is not permitted.
*/
+ @Deprecated(
+ level = DeprecationLevel.WARNING,
+ message = "This option will be merged into StrictNullChecks in 2.23.",
+ replaceWith = ReplaceWith("StrictNullChecks")
+ )
NewStrictNullChecks(enabledByDefault = false);
internal val bitSet: BitSet = (1 shl ordinal).toBitSet()
diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModule.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModule.kt
index d23afd4e..c36dca09 100644
--- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModule.kt
+++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModule.kt
@@ -43,11 +43,10 @@ class KotlinModule private constructor(
val nullToEmptyMap: Boolean = NullToEmptyMap.enabledByDefault,
val nullIsSameAsDefault: Boolean = NullIsSameAsDefault.enabledByDefault,
val singletonSupport: Boolean = SingletonSupport.enabledByDefault,
- @Suppress("DEPRECATION_ERROR")
strictNullChecks: Boolean = StrictNullChecks.enabledByDefault,
val kotlinPropertyNameAsImplicitName: Boolean = KotlinPropertyNameAsImplicitName.enabledByDefault,
val useJavaDurationConversion: Boolean = UseJavaDurationConversion.enabledByDefault,
- private val newStrictNullChecks: Boolean = NewStrictNullChecks.enabledByDefault,
+ newStrictNullChecks: Boolean = NewStrictNullChecks.enabledByDefault,
) : SimpleModule(KotlinModule::class.java.name, PackageVersion.VERSION) {
/*
* Prior to 2.18, an older Enum called SingletonSupport was used to manage feature.
@@ -67,8 +66,6 @@ class KotlinModule private constructor(
)
val enabledSingletonSupport: Boolean get() = singletonSupport
- private val oldStrictNullChecks: Boolean = strictNullChecks
-
// To reduce the amount of destructive changes, no properties will be added to the public.
val strictNullChecks: Boolean = if (strictNullChecks) {
if (newStrictNullChecks) {
@@ -113,7 +110,7 @@ class KotlinModule private constructor(
val cache = ReflectionCache(reflectionCacheSize)
- context.addValueInstantiators(KotlinInstantiators(cache, nullToEmptyCollection, nullToEmptyMap, nullIsSameAsDefault, oldStrictNullChecks))
+ context.addValueInstantiators(KotlinInstantiators(cache, nullToEmptyCollection, nullToEmptyMap, nullIsSameAsDefault))
if (singletonSupport) {
context.addBeanDeserializerModifier(KotlinBeanDeserializerModifier)
@@ -128,7 +125,7 @@ class KotlinModule private constructor(
useJavaDurationConversion
))
context.appendAnnotationIntrospector(
- KotlinNamesAnnotationIntrospector(cache, newStrictNullChecks, kotlinPropertyNameAsImplicitName)
+ KotlinNamesAnnotationIntrospector(cache, strictNullChecks, kotlinPropertyNameAsImplicitName)
)
context.addDeserializers(KotlinDeserializers(cache, useJavaDurationConversion))
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 99fbaab7..06f61113 100644
--- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt
+++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt
@@ -22,16 +22,13 @@ internal class KotlinValueInstantiator(
private val cache: ReflectionCache,
private val nullToEmptyCollection: Boolean,
private val nullToEmptyMap: Boolean,
- private val nullIsSameAsDefault: Boolean,
- private val strictNullChecks: Boolean
+ private val nullIsSameAsDefault: Boolean
) : StdValueInstantiator(src) {
private fun JavaType.requireEmptyValue() =
(nullToEmptyCollection && this.isCollectionLikeType) || (nullToEmptyMap && this.isMapLikeType)
private fun KType.isGenericTypeVar() = javaType is TypeVariable<*>
- private fun List.markedNonNullAt(index: Int) = getOrNull(index)?.type?.isMarkedNullable == false
-
// If the argument is a value class that wraps nullable and non-null,
// and the input is explicit null, the value class is instantiated with null as input.
private fun requireValueClassSpecialNullValue(
@@ -104,35 +101,6 @@ internal class KotlinValueInstantiator(
).wrapWithPath(this.valueClass, pname)
}
}
- } else if (strictNullChecks) {
- val arguments = paramType.arguments
-
- // To make the behavior the same as deserialization of each element using NullsFailProvider,
- // first wrapWithPath with paramVal and key.
- val ex = when {
- propType.isCollectionLikeType && arguments.markedNonNullAt(0) -> {
- (paramVal as Collection<*>).indexOf(null).takeIf { it >= 0 }?.let {
- InvalidNullException.from(ctxt, jsonProp.fullName, jsonProp.type)
- .wrapWithPath(paramVal, it)
- }
- }
- propType.isMapLikeType && arguments.markedNonNullAt(1) -> {
- (paramVal as Map<*, *>).entries.find { (_, v) -> v == null }?.let { (k, _) ->
- InvalidNullException.from(ctxt, jsonProp.fullName, jsonProp.type)
- .wrapWithPath(paramVal, k.toString())
- }
- }
- propType.isArrayType && arguments.markedNonNullAt(0) -> {
- (paramVal as Array<*>).indexOf(null).takeIf { it >= 0 }?.let {
- InvalidNullException.from(ctxt, jsonProp.fullName, jsonProp.type)
- .wrapWithPath(paramVal, it)
- }
- }
- else -> null
- }
-
- // Then, wrapWithPath with this property.
- ex?.let { throw it.wrapWithPath(this.valueClass, jsonProp.name) }
}
bucket[paramDef] = paramVal
@@ -151,7 +119,6 @@ internal class KotlinInstantiators(
private val nullToEmptyCollection: Boolean,
private val nullToEmptyMap: Boolean,
private val nullIsSameAsDefault: Boolean,
- private val strictNullChecks: Boolean
) : ValueInstantiators {
override fun findValueInstantiator(
deserConfig: DeserializationConfig,
@@ -165,8 +132,7 @@ internal class KotlinInstantiators(
cache,
nullToEmptyCollection,
nullToEmptyMap,
- nullIsSameAsDefault,
- strictNullChecks
+ nullIsSameAsDefault
)
} else {
// TODO: return defaultInstantiator and let default method parameters and nullability go unused? or die with exception:
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinInstantiatorsTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinInstantiatorsTest.kt
index 50286ba7..a223908e 100644
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinInstantiatorsTest.kt
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinInstantiatorsTest.kt
@@ -11,8 +11,7 @@ class KotlinInstantiatorsTest {
ReflectionCache(10),
nullToEmptyCollection = false,
nullToEmptyMap = false,
- nullIsSameAsDefault = false,
- strictNullChecks = false
+ nullIsSameAsDefault = false
)
@Test
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/kogeraIntegration/deser/StrictNullChecksTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/kogeraIntegration/deser/StrictNullChecksTest.kt
index d0d74f09..3cad0edc 100644
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/kogeraIntegration/deser/StrictNullChecksTest.kt
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/kogeraIntegration/deser/StrictNullChecksTest.kt
@@ -16,7 +16,7 @@ class StrictNullChecksTest {
val mapper: ObjectMapper = ObjectMapper()
.registerModule(
KotlinModule.Builder()
- .enable(KotlinFeature.NewStrictNullChecks)
+ .enable(KotlinFeature.StrictNullChecks)
.build()
)
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTest.kt
index 2681e846..19178471 100644
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTest.kt
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTest.kt
@@ -2,7 +2,7 @@ package com.fasterxml.jackson.module.kotlin.test
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.exc.InvalidNullException
-import com.fasterxml.jackson.module.kotlin.KotlinFeature.NewStrictNullChecks
+import com.fasterxml.jackson.module.kotlin.KotlinFeature
import com.fasterxml.jackson.module.kotlin.kotlinModule
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Assertions.assertArrayEquals
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.assertThrows
import kotlin.test.assertNull
class StrictNullChecksTest {
- private val mapper = ObjectMapper().registerModule(kotlinModule { enable(NewStrictNullChecks) })
+ private val mapper = ObjectMapper().registerModule(kotlinModule { enable(KotlinFeature.StrictNullChecks) })
/** collection tests */
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTestOld.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTestOld.kt
deleted file mode 100644
index d2301d27..00000000
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/StrictNullChecksTestOld.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.fasterxml.jackson.module.kotlin.test
-
-import com.fasterxml.jackson.databind.exc.InvalidNullException
-import com.fasterxml.jackson.module.kotlin.KotlinFeature
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
-import org.junit.jupiter.api.Assertions.assertArrayEquals
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Disabled
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import kotlin.test.assertNull
-
-class StrictNullChecksTestOld {
- private val mapper = jacksonObjectMapper {
- disable(KotlinFeature.NewStrictNullChecks)
- enable(KotlinFeature.StrictNullChecks)
- }
-
- /** collection tests */
-
- private data class ClassWithListOfNullableInt(val samples: List)
-
- @Test
- fun testListOfNullableInt() {
- val json = """{"samples":[1, null]}"""
- val stateObj = mapper.readValue(json)
- assertEquals(listOf(1, null), stateObj.samples)
- }
-
- private data class ClassWithListOfInt(val samples: List)
-
- @Test
- fun testListOfInt() {
- assertThrows {
- val json = """{"samples":[1, null]}"""
- mapper.readValue(json)
- }
- }
-
- private data class ClassWithNullableListOfInt(val samples: List?)
-
- @Test
- fun testNullableListOfInt() {
- val json = """{"samples": null}"""
- val stateObj = mapper.readValue(json)
- assertNull(stateObj.samples)
- }
-
- /** array tests */
-
- private data class ClassWithArrayOfNullableInt(val samples: Array)
-
- @Test
- fun testArrayOfNullableInt() {
- val json = """{"samples":[1, null]}"""
- val stateObj = mapper.readValue(json)
- assertArrayEquals(arrayOf(1, null), stateObj.samples)
- }
-
- private data class ClassWithArrayOfInt(val samples: Array)
-
- @Test
- fun testArrayOfInt() {
- assertThrows {
- val json = """{"samples":[1, null]}"""
- mapper.readValue(json)
- }
- }
-
- private data class ClassWithNullableArrayOfInt(val samples: Array?)
-
- @Test
- fun testNullableArrayOfInt() {
- val json = """{"samples": null}"""
- val stateObj = mapper.readValue(json)
- assertNull(stateObj.samples)
- }
-
- /** map tests */
-
- private data class ClassWithMapOfStringToNullableInt(val samples: Map)
-
- @Test
- fun testMapOfStringToNullableInt() {
- val json = """{ "samples": { "key": null } }"""
- val stateObj = mapper.readValue(json)
- assertEquals(mapOf("key" to null), stateObj.samples)
- }
-
- private data class ClassWithMapOfStringToInt(val samples: Map)
-
- @Test
- fun testMapOfStringToIntWithNullValue() {
- assertThrows {
- val json = """{ "samples": { "key": null } }"""
- mapper.readValue(json)
- }
- }
-
- private data class ClassWithNullableMapOfStringToInt(val samples: Map?)
-
- @Test
- fun testNullableMapOfStringToInt() {
- val json = """{"samples": null}"""
- val stateObj = mapper.readValue(json)
- assertNull(stateObj.samples)
- }
-
- /** generics test */
-
- private data class TestClass(val samples: T)
-
- @Test
- fun testListOfGeneric() {
- val json = """{"samples":[1, 2]}"""
- val stateObj = mapper.readValue>>(json)
- assertEquals(listOf(1, 2), stateObj.samples)
- }
-
- @Disabled // this is a hard problem to solve and is currently not addressed
- @Test
- fun testListOfGenericWithNullValue() {
- assertThrows {
- val json = """{"samples":[1, null]}"""
- mapper.readValue>>(json)
- }
- }
-
- @Test
- fun testMapOfGeneric() {
- val json = """{ "samples": { "key": 1 } }"""
- val stateObj = mapper.readValue>>(json)
- assertEquals(mapOf("key" to 1), stateObj.samples)
- }
-
- @Disabled // this is a hard problem to solve and is currently not addressed
- @Test
- fun testMapOfGenericWithNullValue() {
- assertThrows {
- val json = """{ "samples": { "key": null } }"""
- mapper.readValue>>(json)
- }
- }
-
- @Test
- fun testArrayOfGeneric() {
- val json = """{"samples":[1, 2]}"""
- val stateObj = mapper.readValue>>(json)
- assertArrayEquals(arrayOf(1, 2), stateObj.samples)
- }
-
- @Disabled // this is a hard problem to solve and is currently not addressed
- @Test
- fun testArrayOfGenericWithNullValue() {
- assertThrows {
- val json = """{"samples":[1, null]}"""
- mapper.readValue>>(json)
- }
- }
-}
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub757.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub757.kt
index 0245c9b8..f9c00f50 100644
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub757.kt
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub757.kt
@@ -11,7 +11,7 @@ class GitHub757 {
@Test
fun test() {
val kotlinModule = KotlinModule.Builder()
- .enable(KotlinFeature.NewStrictNullChecks)
+ .enable(KotlinFeature.StrictNullChecks)
.build()
val mapper = JsonMapper.builder()
.addModule(kotlinModule)
diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub976.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub976.kt
index 27e2c643..dc448e14 100644
--- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub976.kt
+++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/GitHub976.kt
@@ -18,14 +18,4 @@ class GitHub976 {
om.readValue("""{"list": [""] }""".toByteArray(), PrimitiveList::class.java)
}
}
-
- @Test
- fun newStrictNullChecksRegression() {
- val om = jacksonObjectMapper {
- enable(KotlinFeature.NewStrictNullChecks)
- }
- assertThrows {
- om.readValue("""{"list": [""] }""".toByteArray(), PrimitiveList::class.java)
- }
- }
}