Use target collection type for binding

This commit ensures that the `GraphQlArgumentBinder` is using the target
collection type (on the type we're binding to) to create a new
collection instance when using constructor binding.

Fixes gh-485
This commit is contained in:
Brian Clozel
2022-09-08 15:44:36 +02:00
parent c12b46fc11
commit 471834782d
2 changed files with 44 additions and 1 deletions

View File

@@ -209,7 +209,7 @@ public class GraphQlArgumentBinder {
return Collections.emptyList();
}
Collection<T> collection = CollectionFactory.createApproximateCollection(rawCollection, rawCollection.size());
Collection<T> collection = CollectionFactory.createCollection(collectionType.getRawClass(), elementClass, rawCollection.size());
int i = 0;
for (Object rawValue : rawCollection) {
segments.push("[" + i++ + "]");

View File

@@ -19,8 +19,11 @@ package org.springframework.graphql.data;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@@ -268,6 +271,16 @@ class GraphQlArgumentBinderTests {
assertThat(((ItemListHolder) result).getItems()).hasSize(260);
}
@Test
void shouldUseTargetCollectionType() throws Exception {
String items = IntStream.range(0, 5).mapToObj(value -> "{\"name\":\"test" + value + "\"}").collect(Collectors.joining(","));
Object result = this.binder.bind(
environment("{\"key\":{\"items\":[" + items + "]}}"), "key",
ResolvableType.forClass(ItemSetHolder.class));
assertThat(result).isNotNull().isInstanceOf(ItemSetHolder.class);
assertThat(((ItemSetHolder) result).getItems()).hasSize(5);
}
@SuppressWarnings("unchecked")
private DataFetchingEnvironment environment(String jsonPayload) throws JsonProcessingException {
@@ -401,6 +414,36 @@ class GraphQlArgumentBinderTests {
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return name.equals(item.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
static class ItemSetHolder {
private Set<Item> items;
public ItemSetHolder(Set<Item> items) {
this.items = items;
}
public Set<Item> getItems() {
return items;
}
public void setItems(Set<Item> items) {
this.items = items;
}
}
}