|
16 | 16 | package org.springframework.graphql.data.method.annotation.support; |
17 | 17 |
|
18 | 18 | import java.lang.reflect.Constructor; |
19 | | -import java.util.Collection; |
20 | | -import java.util.Iterator; |
21 | | -import java.util.Map; |
22 | | -import java.util.Optional; |
23 | | -import java.util.Stack; |
| 19 | +import java.util.*; |
24 | 20 |
|
25 | 21 | import graphql.schema.DataFetchingEnvironment; |
26 | 22 |
|
@@ -107,13 +103,32 @@ private Object convert(Object rawValue, Class<?> targetType) { |
107 | 103 | Object target; |
108 | 104 | if (rawValue instanceof Map) { |
109 | 105 | 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); |
| 106 | + MutablePropertyValues propertyValues = extractPropertyValues((Map) rawValue); |
| 107 | + |
| 108 | + if (ctor.getParameterCount() == 0) { |
| 109 | + target = BeanUtils.instantiateClass(ctor); |
| 110 | + DataBinder dataBinder = new DataBinder(target); |
| 111 | + dataBinder.bind(propertyValues); |
| 112 | + } else { |
| 113 | + // Data class constructor |
| 114 | + DataBinder binder = new DataBinder(null); |
| 115 | + String[] paramNames = BeanUtils.getParameterNames(ctor); |
| 116 | + Class<?>[] paramTypes = ctor.getParameterTypes(); |
| 117 | + Object[] args = new Object[paramTypes.length]; |
| 118 | + for (int i = 0; i < paramNames.length; i++) { |
| 119 | + String paramName = paramNames[i]; |
| 120 | + Object value = propertyValues.get(paramName); |
| 121 | + value = (value instanceof List ? ((List<?>) value).toArray() : value); |
| 122 | + MethodParameter methodParam = new MethodParameter(ctor, i); |
| 123 | + if (value == null && methodParam.isOptional()) { |
| 124 | + args[i] = (methodParam.getParameterType() == Optional.class ? Optional.empty() : null); |
| 125 | + } |
| 126 | + else { |
| 127 | + args[i] = binder.convertIfNecessary(value, paramTypes[i], methodParam); |
| 128 | + } |
| 129 | + } |
| 130 | + target = BeanUtils.instantiateClass(ctor, args); |
| 131 | + } |
117 | 132 | } |
118 | 133 | else if (targetType.isAssignableFrom(rawValue.getClass())) { |
119 | 134 | return returnValue(rawValue, targetType); |
|
0 commit comments