Relax List input check in GraphQlArgumentBinder

Allow any List type, not only ArrayList and LinkedList but also others
like SingletonList.

Fixes gh-410
This commit is contained in:
rstoyanchev
2022-07-05 07:32:13 +01:00
parent e173bef291
commit 28e3a8c9a3
2 changed files with 34 additions and 2 deletions

View File

@@ -128,7 +128,7 @@ public class GraphQlArgumentBinder {
try {
// From Collection
if (CollectionFactory.isApproximableCollectionType(rawValue.getClass())) {
if (isApproximableCollectionType(rawValue)) {
segments.push(argumentName);
return createCollection((Collection<Object>) rawValue, targetType, bindingResult, segments);
}
@@ -164,6 +164,11 @@ public class GraphQlArgumentBinder {
return (type.resolve(Object.class).equals(Optional.class) ? Optional.ofNullable(value) : value);
}
private boolean isApproximableCollectionType(Object rawValue) {
return (CollectionFactory.isApproximableCollectionType(rawValue.getClass()) ||
rawValue instanceof List); // it may be SingletonList
}
@SuppressWarnings({"ConstantConditions", "unchecked"})
private <T> Collection<T> createCollection(
Collection<Object> rawCollection, ResolvableType collectionType,
@@ -253,7 +258,7 @@ public class GraphQlArgumentBinder {
if (rawValue == null && methodParam.isOptional()) {
args[i] = (paramTypes[i] == Optional.class ? Optional.empty() : null);
}
else if (rawValue != null && CollectionFactory.isApproximableCollectionType(rawValue.getClass())) {
else if (rawValue != null && isApproximableCollectionType(rawValue)) {
ResolvableType elementType = ResolvableType.forMethodParameter(methodParam);
args[i] = createCollection((Collection<Object>) rawValue, elementType, bindingResult, segments);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.graphql.data;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -224,6 +226,31 @@ class GraphQlArgumentBinderTests {
});
}
@Test // gh-410
void coercionWithSingletonList() throws Exception {
Map<String, String> itemMap = new HashMap<>();
itemMap.put("name", "Joe");
itemMap.put("age", "37");
Map<String, Object> arguments = new HashMap<>();
arguments.put("key", Collections.singletonList(itemMap));
DataFetchingEnvironment environment =
DataFetchingEnvironmentImpl.newDataFetchingEnvironment().arguments(arguments).build();
Object result = this.binder.bind(environment, "key",
ResolvableType.forClassWithGenerics(List.class, Item.class));
assertThat(result).isNotNull().isInstanceOf(List.class);
List<Item> items = (List<Item>) result;
assertThat(items).hasSize(1);
assertThat(items.get(0).getName()).isEqualTo("Joe");
assertThat(items.get(0).getAge()).isEqualTo(37);
}
@SuppressWarnings("unchecked")
private DataFetchingEnvironment environment(String jsonPayload) throws JsonProcessingException {
Map<String, Object> arguments = this.mapper.readValue(jsonPayload, Map.class);