@@ -15,23 +15,21 @@ import com.fasterxml.jackson.databind.jsontype.NamedType
15
15
import com.fasterxml.jackson.databind.ser.std.StdSerializer
16
16
import com.fasterxml.jackson.module.kotlin.ser.serializers.ValueClassBoxSerializer
17
17
import com.fasterxml.jackson.module.kotlin.ser.serializers.ValueClassStaticJsonValueSerializer
18
+ import kotlinx.metadata.Flag
19
+ import kotlinx.metadata.KmClassifier
20
+ import kotlinx.metadata.KmProperty
21
+ import kotlinx.metadata.jvm.fieldSignature
22
+ import kotlinx.metadata.jvm.getterSignature
23
+ import kotlinx.metadata.jvm.setterSignature
18
24
import java.lang.reflect.AccessibleObject
19
25
import java.lang.reflect.Constructor
20
26
import java.lang.reflect.Field
21
27
import java.lang.reflect.Method
22
- import kotlin.reflect.KClass
23
28
import kotlin.reflect.KFunction
24
- import kotlin.reflect.KMutableProperty1
25
- import kotlin.reflect.KProperty1
26
29
import kotlin.reflect.KType
27
30
import kotlin.reflect.full.createType
28
- import kotlin.reflect.full.declaredMemberProperties
29
- import kotlin.reflect.full.memberProperties
30
- import kotlin.reflect.jvm.javaGetter
31
- import kotlin.reflect.jvm.javaSetter
32
31
import kotlin.reflect.jvm.javaType
33
32
import kotlin.reflect.jvm.kotlinFunction
34
- import kotlin.reflect.jvm.kotlinProperty
35
33
36
34
internal class KotlinAnnotationIntrospector (
37
35
private val context : Module .SetupContext ,
@@ -81,34 +79,29 @@ internal class KotlinAnnotationIntrospector(
81
79
// it will be serialized properly without doing anything.
82
80
if (this .returnType.isUnboxableValueClass()) return null
83
81
}
82
+ val getterSignature = getter.toSignature()
83
+
84
+ val kotlinProperty =
85
+ getter.declaringClass.toKmClass()?.properties?.find { it.getterSignature == getterSignature }
86
+
87
+ (kotlinProperty?.returnType?.classifier as ? KmClassifier .Class )?.let { classifier ->
88
+ // Since there was no way to directly determine whether returnType is a value class or not,
89
+ // Class is restored and processed.
90
+ // If the cost of this process is significant, consider caching it.
91
+ runCatching {
92
+ // Kotlin-specific types such as kotlin.String will cause an error,
93
+ // but value classes will not cause an error, so ignore them
94
+ Class .forName(classifier.name.replace(" ." , " $" ).replace(" /" , " ." ))
95
+ }
96
+ .getOrNull()
97
+ ?.takeIf { it.annotations.any { ann -> ann is JvmInline } }
98
+ ?.let { outerClazz ->
99
+ val innerClazz = getter.returnType
84
100
85
- val kotlinProperty = getter
86
- .declaringClass
87
- .kotlin
88
- .let {
89
- // KotlinReflectionInternalError is raised in GitHub167 test,
90
- // but it looks like an edge case, so it is ignored.
91
- try {
92
- it.memberProperties
93
- } catch (e: Error ) {
94
- null
101
+ ValueClassStaticJsonValueSerializer .createdOrNull(outerClazz, innerClazz)
102
+ ? : @Suppress(" UNCHECKED_CAST" ) (ValueClassBoxSerializer (outerClazz, innerClazz))
95
103
}
96
- }?.find { it.javaGetter == getter }
97
-
98
- (kotlinProperty?.returnType?.classifier as ? KClass <* >)
99
- ?.takeIf { it.isValue }
100
- ?.java
101
- ?.let { outerClazz ->
102
- val innerClazz = getter.returnType
103
-
104
- ValueClassStaticJsonValueSerializer .createdOrNull(outerClazz, innerClazz)
105
- ? : @Suppress(" UNCHECKED_CAST" ) (
106
- ValueClassBoxSerializer (
107
- outerClazz,
108
- innerClazz
109
- )
110
- )
111
- }
104
+ }
112
105
}
113
106
// Ignore the case of AnnotatedField, because JvmField cannot be set in the field of value class.
114
107
else -> null
@@ -131,8 +124,14 @@ internal class KotlinAnnotationIntrospector(
131
124
}
132
125
133
126
private fun AnnotatedField.hasRequiredMarker (): Boolean? {
134
- val byAnnotation = (member as Field ).isRequiredByAnnotation()
135
- val byNullability = (member as Field ).kotlinProperty?.returnType?.isRequired()
127
+ val member = member as Field
128
+
129
+ val byAnnotation = member.isRequiredByAnnotation()
130
+ val fieldSignature = member.toSignature()
131
+ val byNullability = member.declaringClass.toKmClass()
132
+ ?.properties
133
+ ?.find { it.fieldSignature == fieldSignature }
134
+ ?.let { ! Flag .Type .IS_NULLABLE (it.returnType.flags) }
136
135
137
136
return requiredAnnotationOrNullability(byAnnotation, byNullability)
138
137
}
@@ -155,20 +154,19 @@ internal class KotlinAnnotationIntrospector(
155
154
return (this .annotations.firstOrNull { it.annotationClass.java == JsonProperty ::class .java } as ? JsonProperty )?.required
156
155
}
157
156
158
- // Since Kotlin's property has the same Type for each field, getter, and setter,
159
- // nullability can be determined from the returnType of KProperty.
160
- private fun KProperty1 <* , * >.isRequiredByNullability () = returnType.isRequired()
157
+ private fun KmProperty.isRequiredByNullability (): Boolean = ! Flag .Type .IS_NULLABLE (this .returnType.flags)
161
158
162
159
// This could be a setter or a getter of a class property or
163
160
// a setter-like/getter-like method.
164
161
private fun AnnotatedMethod.hasRequiredMarker (): Boolean? = this .getRequiredMarkerFromCorrespondingAccessor()
165
162
? : this .member.getRequiredMarkerFromAccessorLikeMethod()
166
163
167
164
private fun AnnotatedMethod.getRequiredMarkerFromCorrespondingAccessor (): Boolean? {
168
- member.declaringClass.kotlin.declaredMemberProperties.forEach { kProperty ->
169
- if (kProperty.javaGetter == this .member || (kProperty as ? KMutableProperty1 )?.javaSetter == this .member) {
165
+ val memberSignature = member.toSignature()
166
+ member.declaringClass.toKmClass()?.properties?.forEach { kmProperty ->
167
+ if (kmProperty.getterSignature == memberSignature || kmProperty.setterSignature == memberSignature) {
170
168
val byAnnotation = this .member.isRequiredByAnnotation()
171
- val byNullability = kProperty .isRequiredByNullability()
169
+ val byNullability = kmProperty .isRequiredByNullability()
172
170
return requiredAnnotationOrNullability(byAnnotation, byNullability)
173
171
}
174
172
}
0 commit comments