Skip to content

Commit c31af6e

Browse files
committed
Fix AnnotationIntrospector
1 parent ef318c2 commit c31af6e

File tree

1 file changed

+16
-35
lines changed

1 file changed

+16
-35
lines changed

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

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package com.fasterxml.jackson.module.kotlin
33
import com.fasterxml.jackson.annotation.JsonCreator
44
import com.fasterxml.jackson.annotation.JsonProperty
55
import com.fasterxml.jackson.databind.DeserializationFeature
6+
import com.fasterxml.jackson.databind.JsonSerializer
67
import com.fasterxml.jackson.databind.Module
78
import com.fasterxml.jackson.databind.cfg.MapperConfig
89
import com.fasterxml.jackson.databind.introspect.*
910
import com.fasterxml.jackson.databind.jsontype.NamedType
1011
import com.fasterxml.jackson.databind.ser.std.StdSerializer
12+
import com.fasterxml.jackson.databind.util.Converter
1113
import java.lang.reflect.AccessibleObject
1214
import java.lang.reflect.Constructor
1315
import java.lang.reflect.Field
@@ -62,44 +64,23 @@ internal class KotlinAnnotationIntrospector(private val context: Module.SetupCon
6264
return super.findCreatorAnnotation(config, a)
6365
}
6466

65-
// Find a serializer to handle the case where the getter returns an unboxed value from the value class.
66-
override fun findSerializer(am: Annotated): StdSerializer<*>? = when (am) {
67-
is AnnotatedMethod -> {
68-
val getter = am.member.apply {
69-
// If the return value of the getter is a value class,
70-
// it will be serialized properly without doing anything.
71-
if (this.returnType.isUnboxableValueClass()) return null
72-
}
73-
74-
val kotlinProperty = getter
75-
.declaringClass
76-
.kotlin
77-
.let {
78-
// KotlinReflectionInternalError is raised in GitHub167 test,
79-
// but it looks like an edge case, so it is ignored.
80-
try {
81-
it.memberProperties
82-
} catch (e: Error) {
83-
null
84-
}
85-
}?.find { it.javaGetter == getter }
86-
87-
(kotlinProperty?.returnType?.classifier as? KClass<*>)
88-
?.takeIf { it.isValue }
89-
?.java
90-
?.let { outerClazz ->
91-
val innerClazz = getter.returnType
92-
93-
ValueClassStaticJsonValueSerializer.createdOrNull(outerClazz, innerClazz)
94-
?: @Suppress("UNCHECKED_CAST") ValueClassBoxSerializer(outerClazz, innerClazz)
95-
}
96-
}
97-
// Ignore the case of AnnotatedField, because JvmField cannot be set in the field of value class.
98-
else -> null
67+
// Find a converter to handle the case where the getter returns an unboxed value from the value class.
68+
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = (a as? AnnotatedMethod)?.let { _ ->
69+
cache.findValueClassReturnType(a)?.let { cache.getValueClassBoxConverter(a.rawReturnType, it) }
9970
}
10071

72+
// Determine if the unbox result of value class is nullAable
73+
// @see findNullSerializer
74+
private fun KClass<*>.requireRebox(): Boolean =
75+
this.memberProperties.first { it.javaField != null }.returnType.isMarkedNullable
76+
10177
// Perform proper serialization even if the value wrapped by the value class is null.
102-
override fun findNullSerializer(am: Annotated) = findSerializer(am)
78+
// If value is a non-null object type, it must not be reboxing.
79+
override fun findNullSerializer(am: Annotated): JsonSerializer<*>? = (am as? AnnotatedMethod)?.let { _ ->
80+
cache.findValueClassReturnType(am)
81+
?.takeIf { it.requireRebox() }
82+
?.let { cache.getValueClassBoxConverter(am.rawReturnType, it).delegatingSerializer }
83+
}
10384

10485
/**
10586
* Subclasses can be detected automatically for sealed classes, since all possible subclasses are known

0 commit comments

Comments
 (0)