Skip to content

Commit 28e3a8c

Browse files
committed
Relax List input check in GraphQlArgumentBinder
Allow any List type, not only ArrayList and LinkedList but also others like SingletonList. Fixes gh-410
1 parent e173bef commit 28e3a8c

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public Object bind(
128128
try {
129129
// From Collection
130130

131-
if (CollectionFactory.isApproximableCollectionType(rawValue.getClass())) {
131+
if (isApproximableCollectionType(rawValue)) {
132132
segments.push(argumentName);
133133
return createCollection((Collection<Object>) rawValue, targetType, bindingResult, segments);
134134
}
@@ -164,6 +164,11 @@ private Object wrapAsOptionalIfNecessary(@Nullable Object value, ResolvableType
164164
return (type.resolve(Object.class).equals(Optional.class) ? Optional.ofNullable(value) : value);
165165
}
166166

167+
private boolean isApproximableCollectionType(Object rawValue) {
168+
return (CollectionFactory.isApproximableCollectionType(rawValue.getClass()) ||
169+
rawValue instanceof List); // it may be SingletonList
170+
}
171+
167172
@SuppressWarnings({"ConstantConditions", "unchecked"})
168173
private <T> Collection<T> createCollection(
169174
Collection<Object> rawCollection, ResolvableType collectionType,
@@ -253,7 +258,7 @@ private Object createValue(
253258
if (rawValue == null && methodParam.isOptional()) {
254259
args[i] = (paramTypes[i] == Optional.class ? Optional.empty() : null);
255260
}
256-
else if (rawValue != null && CollectionFactory.isApproximableCollectionType(rawValue.getClass())) {
261+
else if (rawValue != null && isApproximableCollectionType(rawValue)) {
257262
ResolvableType elementType = ResolvableType.forMethodParameter(methodParam);
258263
args[i] = createCollection((Collection<Object>) rawValue, elementType, bindingResult, segments);
259264
}

spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.graphql.data;
1818

19+
import java.util.Collections;
20+
import java.util.HashMap;
1921
import java.util.List;
2022
import java.util.Map;
2123

@@ -224,6 +226,31 @@ void primaryConstructorBindingErrorWithNestedBeanList() {
224226
});
225227
}
226228

229+
@Test // gh-410
230+
void coercionWithSingletonList() throws Exception {
231+
232+
Map<String, String> itemMap = new HashMap<>();
233+
itemMap.put("name", "Joe");
234+
itemMap.put("age", "37");
235+
236+
Map<String, Object> arguments = new HashMap<>();
237+
arguments.put("key", Collections.singletonList(itemMap));
238+
239+
DataFetchingEnvironment environment =
240+
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(arguments).build();
241+
242+
Object result = this.binder.bind(environment, "key",
243+
ResolvableType.forClassWithGenerics(List.class, Item.class));
244+
245+
assertThat(result).isNotNull().isInstanceOf(List.class);
246+
List<Item> items = (List<Item>) result;
247+
248+
assertThat(items).hasSize(1);
249+
assertThat(items.get(0).getName()).isEqualTo("Joe");
250+
assertThat(items.get(0).getAge()).isEqualTo(37);
251+
}
252+
253+
227254
@SuppressWarnings("unchecked")
228255
private DataFetchingEnvironment environment(String jsonPayload) throws JsonProcessingException {
229256
Map<String, Object> arguments = this.mapper.readValue(jsonPayload, Map.class);

0 commit comments

Comments
 (0)