20
20
import java .io .IOException ;
21
21
import java .io .StringWriter ;
22
22
import java .io .Writer ;
23
+ import java .lang .reflect .ParameterizedType ;
23
24
import java .lang .reflect .Type ;
25
+ import java .lang .reflect .TypeVariable ;
24
26
import java .nio .charset .Charset ;
25
27
import java .util .Arrays ;
26
28
import java .util .concurrent .atomic .AtomicReference ;
35
37
import com .fasterxml .jackson .databind .MapperFeature ;
36
38
import com .fasterxml .jackson .databind .ObjectMapper ;
37
39
import com .fasterxml .jackson .databind .SerializationFeature ;
40
+ import com .fasterxml .jackson .databind .type .TypeFactory ;
38
41
39
42
import org .springframework .core .MethodParameter ;
43
+ import org .springframework .core .ResolvableType ;
40
44
import org .springframework .messaging .Message ;
41
45
import org .springframework .messaging .MessageHeaders ;
42
46
import org .springframework .util .Assert ;
@@ -202,7 +206,7 @@ protected boolean supports(Class<?> clazz) {
202
206
203
207
@ Override
204
208
protected Object convertFromInternal (Message <?> message , Class <?> targetClass , Object conversionHint ) {
205
- JavaType javaType = this . objectMapper . constructType (targetClass );
209
+ JavaType javaType = getJavaType (targetClass , conversionHint );
206
210
Object payload = message .getPayload ();
207
211
Class <?> view = getSerializationView (conversionHint );
208
212
// Note: in the view case, calling withType instead of forType for compatibility with Jackson <2.5
@@ -229,6 +233,81 @@ protected Object convertFromInternal(Message<?> message, Class<?> targetClass, O
229
233
}
230
234
}
231
235
236
+ private JavaType getJavaType (Class <?> targetClass , Object conversionHint ) {
237
+ if (conversionHint instanceof MethodParameter ) {
238
+ MethodParameter param = (MethodParameter ) conversionHint ;
239
+ param = param .nestedIfOptional ();
240
+ Type genericParameterType = param .getNestedGenericParameterType ();
241
+ Class <?> contextClass = param .getContainingClass ();
242
+ Type type = getJavaType (genericParameterType , contextClass );
243
+ return this .objectMapper .getTypeFactory ().constructType (type );
244
+ }
245
+ return this .objectMapper .constructType (targetClass );
246
+ }
247
+
248
+ private JavaType getJavaType (Type type , Class <?> contextClass ) {
249
+ TypeFactory typeFactory = this .objectMapper .getTypeFactory ();
250
+ if (contextClass != null ) {
251
+ ResolvableType resolvedType = ResolvableType .forType (type );
252
+ if (type instanceof TypeVariable ) {
253
+ ResolvableType resolvedTypeVariable = resolveVariable (
254
+ (TypeVariable <?>) type , ResolvableType .forClass (contextClass ));
255
+ if (resolvedTypeVariable != ResolvableType .NONE ) {
256
+ return typeFactory .constructType (resolvedTypeVariable .resolve ());
257
+ }
258
+ }
259
+ else if (type instanceof ParameterizedType && resolvedType .hasUnresolvableGenerics ()) {
260
+ ParameterizedType parameterizedType = (ParameterizedType ) type ;
261
+ Class <?>[] generics = new Class <?>[parameterizedType .getActualTypeArguments ().length ];
262
+ Type [] typeArguments = parameterizedType .getActualTypeArguments ();
263
+ for (int i = 0 ; i < typeArguments .length ; i ++) {
264
+ Type typeArgument = typeArguments [i ];
265
+ if (typeArgument instanceof TypeVariable ) {
266
+ ResolvableType resolvedTypeArgument = resolveVariable (
267
+ (TypeVariable <?>) typeArgument , ResolvableType .forClass (contextClass ));
268
+ if (resolvedTypeArgument != ResolvableType .NONE ) {
269
+ generics [i ] = resolvedTypeArgument .resolve ();
270
+ }
271
+ else {
272
+ generics [i ] = ResolvableType .forType (typeArgument ).resolve ();
273
+ }
274
+ }
275
+ else {
276
+ generics [i ] = ResolvableType .forType (typeArgument ).resolve ();
277
+ }
278
+ }
279
+ return typeFactory .constructType (ResolvableType .
280
+ forClassWithGenerics (resolvedType .getRawClass (), generics ).getType ());
281
+ }
282
+ }
283
+ return typeFactory .constructType (type );
284
+ }
285
+
286
+ private ResolvableType resolveVariable (TypeVariable <?> typeVariable , ResolvableType contextType ) {
287
+ ResolvableType resolvedType ;
288
+ if (contextType .hasGenerics ()) {
289
+ resolvedType = ResolvableType .forType (typeVariable , contextType );
290
+ if (resolvedType .resolve () != null ) {
291
+ return resolvedType ;
292
+ }
293
+ }
294
+
295
+ ResolvableType superType = contextType .getSuperType ();
296
+ if (superType != ResolvableType .NONE ) {
297
+ resolvedType = resolveVariable (typeVariable , superType );
298
+ if (resolvedType .resolve () != null ) {
299
+ return resolvedType ;
300
+ }
301
+ }
302
+ for (ResolvableType ifc : contextType .getInterfaces ()) {
303
+ resolvedType = resolveVariable (typeVariable , ifc );
304
+ if (resolvedType .resolve () != null ) {
305
+ return resolvedType ;
306
+ }
307
+ }
308
+ return ResolvableType .NONE ;
309
+ }
310
+
232
311
@ Override
233
312
protected Object convertToInternal (Object payload , MessageHeaders headers , Object conversionHint ) {
234
313
try {
0 commit comments