@@ -178,8 +178,8 @@ else if (rawValue instanceof Map) {
178178 value = bindMap (name , (Map <String , Object >) rawValue , targetType , targetClass , bindingResult );
179179 }
180180 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 );
183183 }
184184
185185 if (isOptional ) {
@@ -229,8 +229,8 @@ private Object bindMap(
229229 Constructor <?> constructor = BeanUtils .getResolvableConstructor (targetClass );
230230
231231 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 );
234234
235235 bindingResult .popNestedPath ();
236236
@@ -261,7 +261,8 @@ private Map<?, Object> bindMapToMap(
261261
262262 @ Nullable
263263 private Object bindMapToObjectViaConstructor (
264- Map <String , Object > rawMap , Constructor <?> constructor , ArgumentsBindingResult bindingResult ) {
264+ Map <String , Object > rawMap , Constructor <?> constructor , ResolvableType parentType ,
265+ ArgumentsBindingResult bindingResult ) {
265266
266267 String [] paramNames = BeanUtils .getParameterNames (constructor );
267268 Class <?>[] paramTypes = constructor .getParameterTypes ();
@@ -270,8 +271,11 @@ private Object bindMapToObjectViaConstructor(
270271 for (int i = 0 ; i < paramNames .length ; i ++) {
271272 String name = paramNames [i ];
272273 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 );
275279 }
276280
277281 try {
@@ -287,20 +291,26 @@ private Object bindMapToObjectViaConstructor(
287291 }
288292
289293 private Object bindMapToObjectViaSetters (
290- Map <String , Object > rawMap , Constructor <?> constructor , ArgumentsBindingResult bindingResult ) {
294+ Map <String , Object > rawMap , Constructor <?> constructor , ResolvableType parentType ,
295+ ArgumentsBindingResult bindingResult ) {
291296
292297 Object target = BeanUtils .instantiateClass (constructor );
293298 BeanWrapper beanWrapper = PropertyAccessorFactory .forBeanPropertyAccess (target );
294299
295300 for (Map .Entry <String , Object > entry : rawMap .entrySet ()) {
296301 String key = entry .getKey ();
297- TypeDescriptor type = beanWrapper .getPropertyTypeDescriptor (key );
298- if (type == null ) {
302+ TypeDescriptor typeDescriptor = beanWrapper .getPropertyTypeDescriptor (key );
303+ if (typeDescriptor == null ) {
299304 // Ignore unknown property
300305 continue ;
301306 }
307+
308+ ResolvableType targetType =
309+ ResolvableType .forType (typeDescriptor .getResolvableType ().getType (), parentType );
310+
302311 Object value = bindRawValue (
303- key , entry .getValue (), false , type .getResolvableType (), type .getType (), bindingResult );
312+ key , entry .getValue (), false , targetType , typeDescriptor .getType (), bindingResult );
313+
304314 try {
305315 if (value != null ) {
306316 beanWrapper .setPropertyValue (key , value );
@@ -320,18 +330,24 @@ private Object bindMapToObjectViaSetters(
320330 @ SuppressWarnings ("unchecked" )
321331 @ Nullable
322332 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 ) {
324335
325336 Object value = null ;
326337 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 ));
329344 }
330345 catch (TypeMismatchException ex ) {
331346 bindingResult .pushNestedPath (name );
332347 bindingResult .rejectValue (rawValue , ex .getErrorCode (), "Failed to convert argument value" );
333348 bindingResult .popNestedPath ();
334349 }
350+
335351 return (T ) value ;
336352 }
337353
0 commit comments