From 3eb2f2698874c02a5ed24fa24444b16746a1717a Mon Sep 17 00:00:00 2001 From: Donghyeon Kim Date: Fri, 4 Aug 2023 00:46:11 +0900 Subject: [PATCH] Support for value classes resolve: #199 --- .../KotlinNamesAnnotationIntrospector.kt | 6 +++--- .../module/kotlin/ReflectJvmMapping.kt | 16 ++++++++++++++ .../jackson/module/kotlin/ReflectionCache.kt | 2 +- .../module/kotlin/test/ValueClassTest.kt | 21 +++++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectJvmMapping.kt create mode 100644 src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/ValueClassTest.kt 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 858ceb7e..722fa6d6 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinNamesAnnotationIntrospector.kt @@ -118,7 +118,7 @@ internal class KotlinNamesAnnotationIntrospector( if (member is AnnotatedConstructor && member.isKotlinConstructorWithParameters()) cache.checkConstructorIsCreatorAnnotated(member) { hasCreatorAnnotation(it) } else - false + member.name == "box-impl" @Suppress("UNCHECKED_CAST") private fun findKotlinParameterName(param: AnnotatedParameter): String? { @@ -127,11 +127,11 @@ internal class KotlinNamesAnnotationIntrospector( if (member is Constructor<*>) { val ctor = (member as Constructor) val ctorParmCount = ctor.parameterTypes.size - val ktorParmCount = try { ctor.kotlinFunction?.parameters?.size ?: 0 } + val ktorParmCount = try { ctor.kotlinCtor?.parameters?.size ?: 0 } catch (ex: KotlinReflectionInternalError) { 0 } catch (ex: UnsupportedOperationException) { 0 } if (ktorParmCount > 0 && ktorParmCount == ctorParmCount) { - ctor.kotlinFunction?.parameters?.get(param.index)?.name + ctor.kotlinCtor?.parameters?.get(param.index)?.name } else { null } diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectJvmMapping.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectJvmMapping.kt new file mode 100644 index 00000000..3ba84d71 --- /dev/null +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectJvmMapping.kt @@ -0,0 +1,16 @@ +package com.fasterxml.jackson.module.kotlin + +import java.lang.reflect.Constructor +import kotlin.reflect.KFunction +import kotlin.reflect.jvm.javaConstructor + +val Constructor.kotlinCtor: KFunction? + get() { + val kotlinClass = declaringClass.kotlin + return if (kotlinClass.isValue) { + val parameterTypes = this.parameters.map { p -> p.type } + kotlinClass.constructors.firstOrNull { it.parameters.map { p -> p.type.erasedType() } == parameterTypes } + } else { + kotlinClass.constructors.firstOrNull { it.javaConstructor == this } + } + } diff --git a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt index dbcb6b17..9dcf14d1 100644 --- a/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt +++ b/src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt @@ -58,7 +58,7 @@ internal class ReflectionCache(reflectionCacheSize: Int) : Serializable { LRUMap(0, reflectionCacheSize) fun kotlinFromJava(key: Constructor): KFunction? = javaConstructorToKotlin.get(key) - ?: key.kotlinFunction?.let { javaConstructorToKotlin.putIfAbsent(key, it) ?: it } + ?: key.kotlinCtor?.let { javaConstructorToKotlin.putIfAbsent(key, it) ?: it } fun kotlinFromJava(key: Method): KFunction<*>? = javaMethodToKotlin.get(key) ?: key.kotlinFunction?.let { javaMethodToKotlin.putIfAbsent(key, it) ?: it } diff --git a/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/ValueClassTest.kt b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/ValueClassTest.kt new file mode 100644 index 00000000..576cfce9 --- /dev/null +++ b/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/ValueClassTest.kt @@ -0,0 +1,21 @@ +package com.fasterxml.jackson.module.kotlin.test + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.kotlinModule +import org.junit.Assert +import org.junit.Test + +class ValueClassTest { + @JvmInline + value class TestClass(val foo: List) + + @Test + fun `test value class`() { + val mapper = createMapper() + Assert.assertEquals(listOf(1, 2), mapper.readValue("""[1,2]""", TestClass::class.java).foo) + } + + private fun createMapper(): ObjectMapper { + return ObjectMapper().registerModule(kotlinModule()) + } +}