diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt index 98b93908..2d84053e 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt @@ -10,7 +10,9 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMember import com.fasterxml.jackson.databind.introspect.AnnotatedMethod import com.fasterxml.jackson.databind.introspect.AnnotatedParameter import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector -import com.fasterxml.jackson.module.kotlin.deser.StrictNullChecksConverter +import com.fasterxml.jackson.databind.util.Converter +import com.fasterxml.jackson.module.kotlin.deser.CollectionValueStrictNullChecksConverter +import com.fasterxml.jackson.module.kotlin.deser.MapValueStrictNullChecksConverter import com.fasterxml.jackson.module.kotlin.deser.ValueClassUnboxConverter import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueParameter import kotlinx.metadata.Flag @@ -138,15 +140,15 @@ private fun ValueParameter.createValueClassUnboxConverterOrNull(rawType: Class<* // @see com.fasterxml.jackson.module.kotlin._ported.test.StrictNullChecksTest#testListOfGenericWithNullValue private fun ValueParameter.isNullishTypeAt(index: Int) = arguments.getOrNull(index)?.isNullable ?: true -private fun ValueParameter.createStrictNullChecksConverterOrNull(rawType: Class<*>): StrictNullChecksConverter<*>? { +private fun ValueParameter.createStrictNullChecksConverterOrNull(rawType: Class<*>): Converter<*, *>? { @Suppress("UNCHECKED_CAST") return when { Array::class.java.isAssignableFrom(rawType) && !this.isNullishTypeAt(0) -> - StrictNullChecksConverter.ForArray(rawType as Class>, this) + CollectionValueStrictNullChecksConverter.ForArray(this) Iterable::class.java.isAssignableFrom(rawType) && !this.isNullishTypeAt(0) -> - StrictNullChecksConverter.ForIterable(rawType as Class>, this) + CollectionValueStrictNullChecksConverter.ForIterable(this) Map::class.java.isAssignableFrom(rawType) && !this.isNullishTypeAt(1) -> - StrictNullChecksConverter.ForMapValue(rawType as Class>, this) + MapValueStrictNullChecksConverter(this) else -> null } } diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/Converters.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/Converters.kt index 6926974a..0b38c8d3 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/Converters.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/Converters.kt @@ -2,24 +2,21 @@ package com.fasterxml.jackson.module.kotlin.deser import com.fasterxml.jackson.databind.JavaType import com.fasterxml.jackson.databind.type.TypeFactory -import com.fasterxml.jackson.databind.util.Converter +import com.fasterxml.jackson.databind.util.StdConverter import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueParameter -internal class ValueClassUnboxConverter(private val valueClass: Class) : Converter { +internal class ValueClassUnboxConverter(private val valueClass: Class) : StdConverter() { private val unboxMethod = valueClass.getDeclaredMethod("unbox-impl").apply { if (!this.isAccessible) this.isAccessible = true } - private val outType = unboxMethod.returnType override fun convert(value: T): Any? = unboxMethod.invoke(value) override fun getInputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(valueClass) - override fun getOutputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(outType) } -internal sealed class StrictNullChecksConverter : Converter { - protected abstract val clazz: Class +internal sealed class CollectionValueStrictNullChecksConverter : StdConverter() { protected abstract val valueParameter: ValueParameter protected abstract fun getValues(value: T): Iterator<*> @@ -38,27 +35,31 @@ internal sealed class StrictNullChecksConverter : Converter { return value } - override fun getInputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(clazz) - override fun getOutputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(clazz) - class ForIterable( - override val clazz: Class>, override val valueParameter: ValueParameter - ) : StrictNullChecksConverter>() { + ) : CollectionValueStrictNullChecksConverter>() { override fun getValues(value: Iterable<*>): Iterator<*> = value.iterator() } class ForArray( - override val clazz: Class>, override val valueParameter: ValueParameter - ) : StrictNullChecksConverter>() { + ) : CollectionValueStrictNullChecksConverter>() { override fun getValues(value: Array<*>): Iterator<*> = value.iterator() } +} - class ForMapValue( - override val clazz: Class>, - override val valueParameter: ValueParameter - ) : StrictNullChecksConverter>() { - override fun getValues(value: Map<*, *>): Iterator<*> = value.values.iterator() +internal class MapValueStrictNullChecksConverter( + private val valueParameter: ValueParameter +) : StdConverter, Map<*, *>>() { + override fun convert(value: Map<*, *>): Map<*, *> = value.apply { + entries.forEach { (k, v) -> + if (v == null) { + throw MissingKotlinParameterException( + valueParameter, + null, + "A null value was entered for key $k of the parameter ${valueParameter.name}." + ) + } + } } }