16
16
17
17
package org .springframework .http .codec ;
18
18
19
+ import java .lang .reflect .Method ;
19
20
import java .lang .reflect .Type ;
20
21
import java .util .Arrays ;
21
22
import java .util .HashSet ;
22
23
import java .util .List ;
23
24
import java .util .Map ;
24
25
import java .util .Set ;
25
26
27
+ import kotlin .reflect .KFunction ;
28
+ import kotlin .reflect .KType ;
29
+ import kotlin .reflect .full .KCallables ;
30
+ import kotlin .reflect .jvm .ReflectJvmMapping ;
26
31
import kotlinx .serialization .KSerializer ;
27
32
import kotlinx .serialization .SerialFormat ;
28
33
import kotlinx .serialization .SerializersKt ;
29
34
import kotlinx .serialization .descriptors .PolymorphicKind ;
30
35
import kotlinx .serialization .descriptors .SerialDescriptor ;
31
36
37
+ import org .springframework .core .KotlinDetector ;
38
+ import org .springframework .core .MethodParameter ;
32
39
import org .springframework .core .ResolvableType ;
33
40
import org .springframework .lang .Nullable ;
41
+ import org .springframework .util .Assert ;
34
42
import org .springframework .util .ConcurrentReferenceHashMap ;
35
43
import org .springframework .util .MimeType ;
36
44
46
54
*/
47
55
public abstract class KotlinSerializationSupport <T extends SerialFormat > {
48
56
49
- private final Map <Type , KSerializer <Object >> serializerCache = new ConcurrentReferenceHashMap <>();
57
+ private final Map <Type , KSerializer <Object >> typeSerializerCache = new ConcurrentReferenceHashMap <>();
58
+
59
+ private final Map <KType , KSerializer <Object >> kTypeSerializerCache = new ConcurrentReferenceHashMap <>();
60
+
50
61
51
62
private final T format ;
52
63
@@ -117,8 +128,33 @@ private boolean supports(@Nullable MimeType mimeType) {
117
128
*/
118
129
@ Nullable
119
130
protected final KSerializer <Object > serializer (ResolvableType resolvableType ) {
131
+ if (resolvableType .getSource () instanceof MethodParameter parameter ) {
132
+ Method method = parameter .getMethod ();
133
+ Assert .notNull (method , "Method must not be null" );
134
+ if (KotlinDetector .isKotlinType (method .getDeclaringClass ())) {
135
+ KFunction <?> function = ReflectJvmMapping .getKotlinFunction (method );
136
+ Assert .notNull (function , "Kotlin function must not be null" );
137
+ KType type = (parameter .getParameterIndex () == -1 ? function .getReturnType () :
138
+ KCallables .getValueParameters (function ).get (parameter .getParameterIndex ()).getType ());
139
+ KSerializer <Object > serializer = this .kTypeSerializerCache .get (type );
140
+ if (serializer == null ) {
141
+ try {
142
+ serializer = SerializersKt .serializerOrNull (this .format .getSerializersModule (), type );
143
+ }
144
+ catch (IllegalArgumentException ignored ) {
145
+ }
146
+ if (serializer != null ) {
147
+ if (hasPolymorphism (serializer .getDescriptor (), new HashSet <>())) {
148
+ return null ;
149
+ }
150
+ this .kTypeSerializerCache .put (type , serializer );
151
+ }
152
+ }
153
+ return serializer ;
154
+ }
155
+ }
120
156
Type type = resolvableType .getType ();
121
- KSerializer <Object > serializer = this .serializerCache .get (type );
157
+ KSerializer <Object > serializer = this .typeSerializerCache .get (type );
122
158
if (serializer == null ) {
123
159
try {
124
160
serializer = SerializersKt .serializerOrNull (this .format .getSerializersModule (), type );
@@ -129,7 +165,7 @@ protected final KSerializer<Object> serializer(ResolvableType resolvableType) {
129
165
if (hasPolymorphism (serializer .getDescriptor (), new HashSet <>())) {
130
166
return null ;
131
167
}
132
- this .serializerCache .put (type , serializer );
168
+ this .typeSerializerCache .put (type , serializer );
133
169
}
134
170
}
135
171
return serializer ;
0 commit comments