Skip to content

Commit f2866db

Browse files
committed
support data classes for method arguments
1 parent bb1a526 commit f2866db

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/ArgumentMethodArgumentResolver.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.lang.reflect.Constructor;
1919
import java.util.Collection;
2020
import java.util.Iterator;
21+
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Optional;
2324
import java.util.Stack;
@@ -107,13 +108,32 @@ private Object convert(Object rawValue, Class<?> targetType) {
107108
Object target;
108109
if (rawValue instanceof Map) {
109110
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+
}
117137
}
118138
else if (targetType.isAssignableFrom(rawValue.getClass())) {
119139
return returnValue(rawValue, targetType);

0 commit comments

Comments
 (0)