Skip to content

Commit c50d23d

Browse files
committed
support data classes for method arguments
1 parent 2777032 commit c50d23d

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

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

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616
package org.springframework.graphql.data.method.annotation.support;
1717

1818
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.*;
2420

2521
import graphql.schema.DataFetchingEnvironment;
2622

@@ -107,13 +103,32 @@ private Object convert(Object rawValue, Class<?> targetType) {
107103
Object target;
108104
if (rawValue instanceof Map) {
109105
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+
}
117132
}
118133
else if (targetType.isAssignableFrom(rawValue.getClass())) {
119134
return returnValue(rawValue, targetType);

0 commit comments

Comments
 (0)