From ac32eb8c5d998cb2537dec520a06f9554babc765 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 8 Jul 2023 19:27:14 +0900 Subject: [PATCH 1/3] Remove MissingKotlinParameterException and replace with MismatchedInputException fixes #617 --- .../jackson/module/kotlin/Exceptions.kt | 32 ------------------- .../module/kotlin/KotlinValueInstantiator.kt | 19 ++++++----- 2 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt deleted file mode 100644 index 3aec2fea..00000000 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/Exceptions.kt +++ /dev/null @@ -1,32 +0,0 @@ -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 6fe13297..98dbdd77 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinValueInstantiator.kt @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.deser.ValueInstantiators import com.fasterxml.jackson.databind.deser.impl.NullsAsEmptyProvider import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator +import com.fasterxml.jackson.databind.exc.MismatchedInputException import java.lang.reflect.TypeVariable import kotlin.reflect.KParameter import kotlin.reflect.KType @@ -81,10 +82,12 @@ internal class KotlinValueInstantiator( val isMissingAndRequired = paramVal == null && isMissing && jsonProp.isRequired if (isMissingAndRequired || (!isGenericTypeVar && paramVal == null && !paramDef.type.isMarkedNullable)) { - 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" + throw MismatchedInputException.from( + ctxt.parser, + jsonProp.type, + "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" ).wrapWithPath(this.valueClass, jsonProp.name) } @@ -107,10 +110,10 @@ internal class KotlinValueInstantiator( } if (paramType != null && itemType != null) { - 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" + throw MismatchedInputException.from( + ctxt.parser, + jsonProp.type, + "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) } } From c3a056ff4247a97efada5f63030357875be7779c Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 8 Jul 2023 19:34:24 +0900 Subject: [PATCH 2/3] Fix tests --- .../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 +++++++++++-------- 5 files changed, 23 insertions(+), 39 deletions(-) delete mode 100644 src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt deleted file mode 100644 index 2a15fed5..00000000 --- a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/MissingKotlinParameterExceptionTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -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 b273e304..eaf0abf0 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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 413e046c..dc65f3e0 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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 e2975f00..88f04bf5 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.module.kotlin.MissingKotlinParameterException +import com.fasterxml.jackson.databind.exc.MismatchedInputException 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 = MissingKotlinParameterException::class) + @Test(expected = MismatchedInputException::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 3008edbf..71b06e5b 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.module.kotlin.MissingKotlinParameterException +import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import org.hamcrest.CustomTypeSafeMatcher @@ -106,16 +106,20 @@ 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: MissingKotlinParameterException): Boolean = e.parameter.equals(param) +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 pathMatches(path: String) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with path `$path`") { - override fun matchesSafely(e: MissingKotlinParameterException): Boolean = e.getHumanReadablePath().equals(path) +private fun pathMatches(path: String) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with path `$path`") { + override fun matchesSafely(e: MismatchedInputException): 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: MissingKotlinParameterException): Boolean { +private fun location(line: Int, column: Int) = object : CustomTypeSafeMatcher("MissingKotlinParameterException with location (line=$line, column=$column)") { + override fun matchesSafely(e: MismatchedInputException): Boolean { return e.location != null && line.equals(e.location.lineNr) && column.equals(e.location.columnNr) } } @@ -131,4 +135,4 @@ private fun JsonMappingException.getHumanReadablePath(): String { } } return builder.toString() -} \ No newline at end of file +} From a90463cd2f239203a12d0d83c02456cbe820a5d8 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 8 Jul 2023 19:43:52 +0900 Subject: [PATCH 3/3] Update release notes wrt #682 --- release-notes/CREDITS-2.x | 5 +++++ release-notes/VERSION-2.x | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 9faa366d..fdb6dc75 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -15,6 +15,11 @@ Authors: Contributors: +# 2.16.0 (not yet released) + +WrongWrong (@k163377) +* #682: Remove MissingKotlinParameterException and replace with MismatchedInputException + # 2.15.2 WrongWrong (@k163377) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index b5204404..bf1c4b9a 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -16,7 +16,11 @@ Co-maintainers: === Releases === ------------------------------------------------------------------------ -2.16.0 (not yet relesed) +2.16.0 (not yet released) + +#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.2 (30-May-2023)