Skip to content

Commit 85de078

Browse files
committed
Added NewStrictNullChecks option
1 parent 4ecdac2 commit 85de078

File tree

4 files changed

+59
-5
lines changed

4 files changed

+59
-5
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinFeature.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.fasterxml.jackson.module.kotlin
22

3+
import com.fasterxml.jackson.annotation.JsonSetter
4+
import com.fasterxml.jackson.databind.exc.InvalidNullException
35
import java.util.BitSet
46

57
/**
@@ -40,6 +42,11 @@ enum class KotlinFeature(internal val enabledByDefault: Boolean) {
4042
* may contain null values after deserialization.
4143
* Enabling it protects against this but has significant performance impact.
4244
*/
45+
@Deprecated(
46+
level = DeprecationLevel.WARNING,
47+
message = "This option will be migrated to the new backend in 2.21.",
48+
replaceWith = ReplaceWith("NewStrictNullChecks")
49+
)
4350
StrictNullChecks(enabledByDefault = false),
4451

4552
/**
@@ -66,7 +73,23 @@ enum class KotlinFeature(internal val enabledByDefault: Boolean) {
6673
* `@JsonFormat` annotations need to be declared either on getter using `@get:JsonFormat` or field using `@field:JsonFormat`.
6774
* See [jackson-module-kotlin#651] for details.
6875
*/
69-
UseJavaDurationConversion(enabledByDefault = false);
76+
UseJavaDurationConversion(enabledByDefault = false),
77+
78+
/**
79+
* New [StrictNullChecks] feature with improved throughput.
80+
* Internally, it will be the same as if [JsonSetter] (contentNulls = FAIL) had been granted.
81+
* Benchmarks show that it can check for illegal nulls with throughput nearly identical to the default (see [jackson-module-kotlin#719]).
82+
*
83+
* Note that in the new backend, the exception thrown has changed from [MissingKotlinParameterException] to [InvalidNullException].
84+
* The message will be changed accordingly.
85+
* Since 2.19, the base class of [MissingKotlinParameterException] has also been changed to [InvalidNullException],
86+
* so be careful when catching it.
87+
*
88+
* This is a temporary option for a phased backend migration,
89+
* which will eventually be merged into [StrictNullChecks].
90+
* Also, specifying both this and [StrictNullChecks] is not permitted.
91+
*/
92+
NewStrictNullChecks(enabledByDefault = false);
7093

7194
internal val bitSet: BitSet = (1 shl ordinal).toBitSet()
7295

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModule.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullToEmptyCollection
77
import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullToEmptyMap
88
import com.fasterxml.jackson.module.kotlin.KotlinFeature.SingletonSupport
99
import com.fasterxml.jackson.module.kotlin.KotlinFeature.StrictNullChecks
10+
import com.fasterxml.jackson.module.kotlin.KotlinFeature.NewStrictNullChecks
1011
import com.fasterxml.jackson.module.kotlin.KotlinFeature.KotlinPropertyNameAsImplicitName
1112
import com.fasterxml.jackson.module.kotlin.KotlinFeature.UseJavaDurationConversion
1213
import java.util.*
@@ -42,9 +43,10 @@ class KotlinModule private constructor(
4243
val nullToEmptyMap: Boolean = NullToEmptyMap.enabledByDefault,
4344
val nullIsSameAsDefault: Boolean = NullIsSameAsDefault.enabledByDefault,
4445
val singletonSupport: Boolean = SingletonSupport.enabledByDefault,
45-
val strictNullChecks: Boolean = StrictNullChecks.enabledByDefault,
46+
strictNullChecks: Boolean = StrictNullChecks.enabledByDefault,
4647
val kotlinPropertyNameAsImplicitName: Boolean = KotlinPropertyNameAsImplicitName.enabledByDefault,
4748
val useJavaDurationConversion: Boolean = UseJavaDurationConversion.enabledByDefault,
49+
private val newStrictNullChecks: Boolean = NewStrictNullChecks.enabledByDefault,
4850
) : SimpleModule(KotlinModule::class.java.name, PackageVersion.VERSION) {
4951
/*
5052
* Prior to 2.18, an older Enum called SingletonSupport was used to manage feature.
@@ -64,6 +66,19 @@ class KotlinModule private constructor(
6466
)
6567
val enabledSingletonSupport: Boolean get() = singletonSupport
6668

69+
private val oldStrictNullChecks: Boolean = strictNullChecks
70+
71+
// To reduce the amount of destructive changes, no properties will be added to the public.
72+
val strictNullChecks: Boolean = if (strictNullChecks) {
73+
if (newStrictNullChecks) {
74+
throw IllegalArgumentException("Enabling both StrictNullChecks and NewStrictNullChecks is not permitted.")
75+
}
76+
77+
true
78+
} else {
79+
newStrictNullChecks
80+
}
81+
6782
companion object {
6883
// Increment when option is added
6984
private const val serialVersionUID = 3L
@@ -84,6 +99,7 @@ class KotlinModule private constructor(
8499
builder.isEnabled(StrictNullChecks),
85100
builder.isEnabled(KotlinPropertyNameAsImplicitName),
86101
builder.isEnabled(UseJavaDurationConversion),
102+
builder.isEnabled(NewStrictNullChecks),
87103
)
88104

89105
override fun setupModule(context: SetupContext) {
@@ -95,7 +111,7 @@ class KotlinModule private constructor(
95111

96112
val cache = ReflectionCache(reflectionCacheSize)
97113

98-
context.addValueInstantiators(KotlinInstantiators(cache, nullToEmptyCollection, nullToEmptyMap, nullIsSameAsDefault, strictNullChecks))
114+
context.addValueInstantiators(KotlinInstantiators(cache, nullToEmptyCollection, nullToEmptyMap, nullIsSameAsDefault, oldStrictNullChecks))
99115

100116
if (singletonSupport) {
101117
context.addBeanDeserializerModifier(KotlinBeanDeserializerModifier)

src/test/kotlin/com/fasterxml/jackson/module/kotlin/DslTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullIsSameAsDefault
66
import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullToEmptyCollection
77
import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullToEmptyMap
88
import com.fasterxml.jackson.module.kotlin.KotlinFeature.SingletonSupport
9-
import com.fasterxml.jackson.module.kotlin.KotlinFeature.StrictNullChecks
9+
import com.fasterxml.jackson.module.kotlin.KotlinFeature.NewStrictNullChecks
1010
import org.junit.jupiter.api.Assertions.assertNotNull
1111
import org.junit.jupiter.api.Test
1212
import kotlin.test.assertEquals
@@ -35,7 +35,7 @@ class DslTest {
3535
enable(NullToEmptyMap)
3636
enable(NullIsSameAsDefault)
3737
enable(SingletonSupport)
38-
enable(StrictNullChecks)
38+
enable(NewStrictNullChecks)
3939
}
4040

4141
assertNotNull(module)

src/test/kotlin/com/fasterxml/jackson/module/kotlin/KotlinModuleTest.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,24 @@ import org.junit.jupiter.api.Assertions.assertEquals
66
import org.junit.jupiter.api.Assertions.assertFalse
77
import org.junit.jupiter.api.Assertions.assertTrue
88
import org.junit.jupiter.api.Test
9+
import org.junit.jupiter.api.assertThrows
910
import kotlin.test.assertNotNull
1011

1112
class KotlinModuleTest {
13+
// After the final migration is complete, this test will be removed.
14+
@Test
15+
fun strictNullChecksTests() {
16+
assertTrue(kotlinModule { enable(StrictNullChecks) }.strictNullChecks)
17+
assertTrue(kotlinModule { enable(NewStrictNullChecks) }.strictNullChecks)
18+
19+
assertThrows<IllegalArgumentException> {
20+
kotlinModule {
21+
enable(StrictNullChecks)
22+
enable(NewStrictNullChecks)
23+
}
24+
}
25+
}
26+
1227
@Test
1328
fun builder_Defaults() {
1429
val module = KotlinModule.Builder().build()

0 commit comments

Comments
 (0)