@@ -178,8 +178,8 @@ else if (rawValue instanceof Map) {
178
178
value = bindMap (name , (Map <String , Object >) rawValue , targetType , targetClass , bindingResult );
179
179
}
180
180
else {
181
- value = (targetClass .isAssignableFrom (rawValue .getClass ()) ?
182
- rawValue : convertValue (name , rawValue , targetClass , bindingResult ));
181
+ value = (! targetClass .isAssignableFrom (rawValue .getClass ()) ?
182
+ convertValue (name , rawValue , targetType , targetClass , bindingResult ) : rawValue );
183
183
}
184
184
185
185
if (isOptional ) {
@@ -229,8 +229,8 @@ private Object bindMap(
229
229
Constructor <?> constructor = BeanUtils .getResolvableConstructor (targetClass );
230
230
231
231
Object value = constructor .getParameterCount () > 0 ?
232
- bindMapToObjectViaConstructor (rawMap , constructor , bindingResult ) :
233
- bindMapToObjectViaSetters (rawMap , constructor , bindingResult );
232
+ bindMapToObjectViaConstructor (rawMap , constructor , targetType , bindingResult ) :
233
+ bindMapToObjectViaSetters (rawMap , constructor , targetType , bindingResult );
234
234
235
235
bindingResult .popNestedPath ();
236
236
@@ -261,7 +261,8 @@ private Map<?, Object> bindMapToMap(
261
261
262
262
@ Nullable
263
263
private Object bindMapToObjectViaConstructor (
264
- Map <String , Object > rawMap , Constructor <?> constructor , ArgumentsBindingResult bindingResult ) {
264
+ Map <String , Object > rawMap , Constructor <?> constructor , ResolvableType parentType ,
265
+ ArgumentsBindingResult bindingResult ) {
265
266
266
267
String [] paramNames = BeanUtils .getParameterNames (constructor );
267
268
Class <?>[] paramTypes = constructor .getParameterTypes ();
@@ -270,8 +271,11 @@ private Object bindMapToObjectViaConstructor(
270
271
for (int i = 0 ; i < paramNames .length ; i ++) {
271
272
String name = paramNames [i ];
272
273
boolean isOmitted = !rawMap .containsKey (name );
273
- ResolvableType paramType = ResolvableType .forConstructorParameter (constructor , i );
274
- args [i ] = bindRawValue (name , rawMap .get (name ), isOmitted , paramType , paramTypes [i ], bindingResult );
274
+
275
+ ResolvableType targetType = ResolvableType .forType (
276
+ ResolvableType .forConstructorParameter (constructor , i ).getType (), parentType );
277
+
278
+ args [i ] = bindRawValue (name , rawMap .get (name ), isOmitted , targetType , paramTypes [i ], bindingResult );
275
279
}
276
280
277
281
try {
@@ -287,20 +291,26 @@ private Object bindMapToObjectViaConstructor(
287
291
}
288
292
289
293
private Object bindMapToObjectViaSetters (
290
- Map <String , Object > rawMap , Constructor <?> constructor , ArgumentsBindingResult bindingResult ) {
294
+ Map <String , Object > rawMap , Constructor <?> constructor , ResolvableType parentType ,
295
+ ArgumentsBindingResult bindingResult ) {
291
296
292
297
Object target = BeanUtils .instantiateClass (constructor );
293
298
BeanWrapper beanWrapper = PropertyAccessorFactory .forBeanPropertyAccess (target );
294
299
295
300
for (Map .Entry <String , Object > entry : rawMap .entrySet ()) {
296
301
String key = entry .getKey ();
297
- TypeDescriptor type = beanWrapper .getPropertyTypeDescriptor (key );
298
- if (type == null ) {
302
+ TypeDescriptor typeDescriptor = beanWrapper .getPropertyTypeDescriptor (key );
303
+ if (typeDescriptor == null ) {
299
304
// Ignore unknown property
300
305
continue ;
301
306
}
307
+
308
+ ResolvableType targetType =
309
+ ResolvableType .forType (typeDescriptor .getResolvableType ().getType (), parentType );
310
+
302
311
Object value = bindRawValue (
303
- key , entry .getValue (), false , type .getResolvableType (), type .getType (), bindingResult );
312
+ key , entry .getValue (), false , targetType , typeDescriptor .getType (), bindingResult );
313
+
304
314
try {
305
315
if (value != null ) {
306
316
beanWrapper .setPropertyValue (key , value );
@@ -320,18 +330,24 @@ private Object bindMapToObjectViaSetters(
320
330
@ SuppressWarnings ("unchecked" )
321
331
@ Nullable
322
332
private <T > T convertValue (
323
- String name , @ Nullable Object rawValue , Class <T > type , ArgumentsBindingResult bindingResult ) {
333
+ String name , @ Nullable Object rawValue , ResolvableType type , Class <T > clazz ,
334
+ ArgumentsBindingResult bindingResult ) {
324
335
325
336
Object value = null ;
326
337
try {
327
- TypeConverter converter = (this .typeConverter != null ? this .typeConverter : new SimpleTypeConverter ());
328
- value = converter .convertIfNecessary (rawValue , (Class <?>) type );
338
+ TypeConverter converter =
339
+ (this .typeConverter != null ? this .typeConverter : new SimpleTypeConverter ());
340
+
341
+ value = converter .convertIfNecessary (
342
+ rawValue , (Class <?>) clazz ,
343
+ (type .getSource () instanceof MethodParameter param ? new TypeDescriptor (param ) : null ));
329
344
}
330
345
catch (TypeMismatchException ex ) {
331
346
bindingResult .pushNestedPath (name );
332
347
bindingResult .rejectValue (rawValue , ex .getErrorCode (), "Failed to convert argument value" );
333
348
bindingResult .popNestedPath ();
334
349
}
350
+
335
351
return (T ) value ;
336
352
}
337
353
0 commit comments