From e9463e92ba96a34cc355f5bd99776ac435dbb184 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 29 Oct 2023 17:06:47 +0900 Subject: [PATCH] Revert "Merge pull request #682 from k163377/fix/617" This reverts commit 43f01ea1f63908f659dec493357bcd235abd221a, reversing changes made to 25a54ffa2babe441d3ee375987b31aec7f0a41bb. --- release-notes/CREDITS-2.x | 1 - release-notes/VERSION-2.x | 3 -- .../jackson/module/kotlin/Exceptions.kt | 32 +++++++++++++++++++ .../module/kotlin/KotlinValueInstantiator.kt | 18 +++++------ .../MissingKotlinParameterExceptionTest.kt | 20 ++++++++++++ .../module/kotlin/test/NullToDefaultTests.kt | 4 +-- .../kotlin/test/StrictNullChecksTest.kt | 14 ++++---- .../module/kotlin/test/github/Github168.kt | 4 +-- .../module/kotlin/test/github/Github32.kt | 20 +++++------- 9 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt create mode 100644 src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index b6ef3c1a..e438bc6c 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -29,7 +29,6 @@ WrongWrong (@k163377) * #686: Add KotlinPropertyNameAsImplicitName option * #685: Streamline default value management for KotlinFeatures * #684: Update Kotlin Version to 1.6 -* #682: Remove MissingKotlinParameterException and replace with MismatchedInputException # 2.15.2 diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 0b514256..3577629e 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -32,9 +32,6 @@ Co-maintainers: #685: Streamline default value management for KotlinFeatures. This improves the initialization cost of kotlin-module a little. #684: Kotlin 1.5 has been deprecated and the minimum supported Kotlin version will be updated to 1.6. -#682: Remove MissingKotlinParameterException and replace with MismatchedInputException - This change removes MissingKotlinParameterException and resolves #617. - This change is a prerequisite for future work to improve performance. 2.15.3 (12-Oct-2023) diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt new file mode 100644 index 00000000..3aec2fea --- /dev/null +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt @@ -0,0 +1,32 @@ +package com.fasterxml.jackson.module.kotlin + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.JsonMappingException +import com.fasterxml.jackson.databind.exc.MismatchedInputException +import java.io.Closeable +import kotlin.reflect.KParameter + +/** + * Specialized [JsonMappingException] sub-class used to indicate that a mandatory Kotlin constructor + * parameter was missing or null. + */ +@Deprecated( + "It will be removed in jackson-module-kotlin 2.16. See #617 for details.", + ReplaceWith( + "MismatchedInputException", + "com.fasterxml.jackson.databind.exc.MismatchedInputException" + ), + DeprecationLevel.WARNING +) +// When deserialized by the JDK, the parameter property will be null, ignoring nullability. +// This is a temporary workaround for #572 and we will eventually remove this class. +class MissingKotlinParameterException(@Transient val parameter: KParameter, + processor: JsonParser? = null, + msg: String) : MismatchedInputException(processor, msg) { + @Deprecated("Use main constructor", ReplaceWith("MissingKotlinParameterException(KParameter, JsonParser?, String)")) + constructor( + parameter: KParameter, + processor: Closeable? = null, + msg: String + ) : this(parameter, processor as JsonParser, msg) +} 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 aebdd2f1..8c473717 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt @@ -98,12 +98,10 @@ internal class KotlinValueInstantiator( // Since #310 reported that the calculation cost is high, isGenericTypeVar is determined last. if (isMissingAndRequired || (!paramType.isMarkedNullable && !paramType.isGenericTypeVar())) { - throw MismatchedInputException.from( - ctxt.parser, - propType, - "Instantiation of $valueTypeDesc value failed for JSON property ${jsonProp.name} " + - "due to missing (therefore NULL) value for creator parameter ${paramDef.name} " + - "which is a non-nullable type" + throw MissingKotlinParameterException( + parameter = paramDef, + processor = ctxt.parser, + msg = "Instantiation of ${this.valueTypeDesc} value failed for JSON property ${jsonProp.name} due to missing (therefore NULL) value for creator parameter ${paramDef.name} which is a non-nullable type" ).wrapWithPath(this.valueClass, jsonProp.name) } } @@ -129,10 +127,10 @@ internal class KotlinValueInstantiator( } if (paramTypeStr != null && itemType != null) { - throw MismatchedInputException.from( - ctxt.parser, - propType, - "Instantiation of $itemType $paramTypeStr failed for JSON property ${jsonProp.name} due to null value in a $paramTypeStr that does not allow null values" + throw MissingKotlinParameterException( + parameter = paramDef, + processor = ctxt.parser, + msg = "Instantiation of $itemType $paramType failed for JSON property ${jsonProp.name} due to null value in a $paramType that does not allow null values" ).wrapWithPath(this.valueClass, jsonProp.name) } } diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt new file mode 100644 index 00000000..2a15fed5 --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt @@ -0,0 +1,20 @@ +package com.fasterxml.jackson.module.kotlin + +import org.junit.Test +import kotlin.test.assertNotNull +import kotlin.test.assertNull + +class MissingKotlinParameterExceptionTest { + @Test + fun jdkSerializabilityTest() { + val param = ::MissingKotlinParameterException.parameters.first() + val ex = MissingKotlinParameterException(param, null, "test") + + val serialized = jdkSerialize(ex) + val deserialized = jdkDeserialize(serialized) + + assertNotNull(deserialized) + // see comment at MissingKotlinParameterException + assertNull(deserialized.parameter) + } +} diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/NullToDefaultTests.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/NullToDefaultTests.kt index eaf0abf0..b273e304 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/NullToDefaultTests.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/NullToDefaultTests.kt @@ -1,8 +1,8 @@ package com.fasterxml.jackson.module.kotlin.test import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.KotlinFeature.NullIsSameAsDefault +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.kotlinModule import com.fasterxml.jackson.module.kotlin.readValue import org.junit.Assert @@ -139,7 +139,7 @@ class TestNullToDefault { Assert.assertEquals(true, item.canBeProcessed) } - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun shouldThrowExceptionWhenProvidedNullForNotNullFieldWithoutDefault() { createMapper(true).readValue( """{ 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 dc65f3e0..413e046c 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 @@ -1,8 +1,8 @@ package com.fasterxml.jackson.module.kotlin.test import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.KotlinFeature.StrictNullChecks +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.kotlinModule import com.fasterxml.jackson.module.kotlin.readValue import org.hamcrest.CoreMatchers.equalTo @@ -27,7 +27,7 @@ class StrictNullChecksTest { private data class ClassWithListOfInt(val samples: List) - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testListOfInt() { val json = """{"samples":[1, null]}""" mapper.readValue(json) @@ -55,7 +55,7 @@ class StrictNullChecksTest { private data class ClassWithArrayOfInt(val samples: Array) - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testArrayOfInt() { val json = """{"samples":[1, null]}""" mapper.readValue(json) @@ -83,7 +83,7 @@ class StrictNullChecksTest { private data class ClassWithMapOfStringToInt(val samples: Map) - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testMapOfStringToIntWithNullValue() { val json = """{ "samples": { "key": null } }""" mapper.readValue(json) @@ -110,7 +110,7 @@ class StrictNullChecksTest { } @Ignore // this is a hard problem to solve and is currently not addressed - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testListOfGenericWithNullValue() { val json = """{"samples":[1, null]}""" mapper.readValue>>(json) @@ -124,7 +124,7 @@ class StrictNullChecksTest { } @Ignore // this is a hard problem to solve and is currently not addressed - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testMapOfGenericWithNullValue() { val json = """{ "samples": { "key": null } }""" mapper.readValue>>(json) @@ -138,7 +138,7 @@ class StrictNullChecksTest { } @Ignore // this is a hard problem to solve and is currently not addressed - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testArrayOfGenericWithNullValue() { val json = """{"samples":[1, null]}""" mapper.readValue>>(json) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github168.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github168.kt index 88f04bf5..e2975f00 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github168.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github168.kt @@ -1,7 +1,7 @@ package com.fasterxml.jackson.module.kotlin.test.github import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import org.junit.Test @@ -17,7 +17,7 @@ class TestGithub168 { assertEquals("whatever", obj.baz) } - @Test(expected = MismatchedInputException::class) + @Test(expected = MissingKotlinParameterException::class) fun testIfRequiredIsReallyRequiredWhenAbsent() { val obj = jacksonObjectMapper().readValue("""{"baz":"whatever"}""") assertEquals("whatever", obj.baz) diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github32.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github32.kt index 71b06e5b..3008edbf 100644 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github32.kt +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/Github32.kt @@ -1,7 +1,7 @@ package com.fasterxml.jackson.module.kotlin.test.github import com.fasterxml.jackson.databind.JsonMappingException -import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import org.hamcrest.CustomTypeSafeMatcher @@ -106,20 +106,16 @@ private data class Crowd(val people: List) private fun missingFirstNameParameter() = missingConstructorParam(::Person.parameters[0]) -private fun missingConstructorParam( - param: KParameter -) = object : CustomTypeSafeMatcher( - "MissingKotlinParameterException with missing `${param.name}` parameter" -) { - override fun matchesSafely(e: MismatchedInputException): Boolean = param.name == e.path.last().fieldName +private fun missingConstructorParam(param: KParameter) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with missing `${param.name}` parameter") { + override fun matchesSafely(e: MissingKotlinParameterException): Boolean = e.parameter.equals(param) } -private fun pathMatches(path: String) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with path `$path`") { - override fun matchesSafely(e: MismatchedInputException): Boolean = e.getHumanReadablePath().equals(path) +private fun pathMatches(path: String) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with path `$path`") { + override fun matchesSafely(e: MissingKotlinParameterException): Boolean = e.getHumanReadablePath().equals(path) } -private fun location(line: Int, column: Int) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with location (line=$line, column=$column)") { - override fun matchesSafely(e: MismatchedInputException): Boolean { +private fun location(line: Int, column: Int) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with location (line=$line, column=$column)") { + override fun matchesSafely(e: MissingKotlinParameterException): Boolean { return e.location != null && line.equals(e.location.lineNr) && column.equals(e.location.columnNr) } } @@ -135,4 +131,4 @@ private fun JsonMappingException.getHumanReadablePath(): String { } } return builder.toString() -} +} \ No newline at end of file