From 28e3a8c9a3924cabcf7e6d3c993d9d02626deec9 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 5 Jul 2022 07:32:13 +0100 Subject: [PATCH] Relax List input check in GraphQlArgumentBinder Allow any List type, not only ArrayList and LinkedList but also others like SingletonList. Fixes gh-410 --- .../graphql/data/GraphQlArgumentBinder.java | 9 +++++-- .../data/GraphQlArgumentBinderTests.java | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java b/spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java index 7388491e..11508ec3 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java @@ -128,7 +128,7 @@ public class GraphQlArgumentBinder { try { // From Collection - if (CollectionFactory.isApproximableCollectionType(rawValue.getClass())) { + if (isApproximableCollectionType(rawValue)) { segments.push(argumentName); return createCollection((Collection) 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 Collection createCollection( Collection 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) rawValue, elementType, bindingResult, segments); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java index f986a336..89949929 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java @@ -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 itemMap = new HashMap<>(); + itemMap.put("name", "Joe"); + itemMap.put("age", "37"); + + Map 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 items = (List) 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 arguments = this.mapper.readValue(jsonPayload, Map.class);