|
18 | 18 | import java.lang.reflect.Constructor;
|
19 | 19 | import java.util.Collection;
|
20 | 20 | import java.util.Iterator;
|
| 21 | +import java.util.List; |
21 | 22 | import java.util.Map;
|
22 | 23 | import java.util.Optional;
|
23 | 24 | import java.util.Stack;
|
@@ -107,13 +108,32 @@ private Object convert(Object rawValue, Class<?> targetType) {
|
107 | 108 | Object target;
|
108 | 109 | if (rawValue instanceof Map) {
|
109 | 110 | Constructor<?> ctor = BeanUtils.getResolvableConstructor(targetType);
|
110 |
| - target = BeanUtils.instantiateClass(ctor); |
111 |
| - DataBinder dataBinder = new DataBinder(target); |
112 |
| - Assert.isTrue(ctor.getParameterCount() == 0, |
113 |
| - () -> "Argument of type [" + targetType.getName() + |
114 |
| - "] cannot be instantiated because of missing default constructor."); |
115 |
| - MutablePropertyValues mpvs = extractPropertyValues((Map) rawValue); |
116 |
| - dataBinder.bind(mpvs); |
| 111 | + MutablePropertyValues propertyValues = extractPropertyValues((Map) rawValue); |
| 112 | + |
| 113 | + if (ctor.getParameterCount() == 0) { |
| 114 | + target = BeanUtils.instantiateClass(ctor); |
| 115 | + DataBinder dataBinder = new DataBinder(target); |
| 116 | + dataBinder.bind(propertyValues); |
| 117 | + } else { |
| 118 | + // Data class constructor |
| 119 | + DataBinder binder = new DataBinder(null); |
| 120 | + String[] paramNames = BeanUtils.getParameterNames(ctor); |
| 121 | + Class<?>[] paramTypes = ctor.getParameterTypes(); |
| 122 | + Object[] args = new Object[paramTypes.length]; |
| 123 | + for (int i = 0; i < paramNames.length; i++) { |
| 124 | + String paramName = paramNames[i]; |
| 125 | + Object value = propertyValues.get(paramName); |
| 126 | + value = (value instanceof List ? ((List<?>) value).toArray() : value); |
| 127 | + MethodParameter methodParam = new MethodParameter(ctor, i); |
| 128 | + if (value == null && methodParam.isOptional()) { |
| 129 | + args[i] = (methodParam.getParameterType() == Optional.class ? Optional.empty() : null); |
| 130 | + } |
| 131 | + else { |
| 132 | + args[i] = binder.convertIfNecessary(value, paramTypes[i], methodParam); |
| 133 | + } |
| 134 | + } |
| 135 | + target = BeanUtils.instantiateClass(ctor, args); |
| 136 | + } |
117 | 137 | }
|
118 | 138 | else if (targetType.isAssignableFrom(rawValue.getClass())) {
|
119 | 139 | return returnValue(rawValue, targetType);
|
|
0 commit comments