Recursively instantiate beans in arguments

This commit ensures that Java beans using primary constructors are
properly instantiated when they're nested and that the instantiation
algorithm is called recursively.

Fixes gh-155
This commit is contained in:
Koen Punt
2021-10-06 11:37:52 +02:00
committed by Brian Clozel
parent 94ff0a2aaf
commit 454c041546
2 changed files with 33 additions and 1 deletions

View File

@@ -89,7 +89,9 @@ class GraphQlArgumentInstantiator {
Class<?> elementType = typeDescriptor.getElementTypeDescriptor().getType();
args[i] = instantiateCollection(elementType, (Collection<Object>) value);
}
else {
else if (value instanceof Map) {
args[i] = this.instantiate((Map<String, Object>) value, methodParam.getParameterType());
} else {
args[i] = this.converter.convertIfNecessary(value, paramTypes[i], methodParam);
}
}

View File

@@ -103,6 +103,17 @@ class GraphQlArgumentInstantiatorTests {
assertThat(result.getItems()).hasSize(2).extracting("name").containsExactly("first", "second");
}
@Test
void shouldInstantiateComplexNestedBean() throws Exception {
String payload = "{\"complex\": { \"item\": {\"name\": \"Item name\"}, \"name\": \"Hello\" } }";
DataFetchingEnvironment environment = initEnvironment(payload);
PrimaryConstructorComplexInput result = instantiator.instantiate(environment.getArgument("complex"), PrimaryConstructorComplexInput.class);
assertThat(result).isNotNull().isInstanceOf(PrimaryConstructorComplexInput.class);
assertThat(result.item.name).isEqualTo("Item name");
assertThat(result.name).isEqualTo("Hello");
}
private DataFetchingEnvironment initEnvironment(String jsonPayload) throws JsonProcessingException {
Map<String, Object> arguments = this.mapper.readValue(jsonPayload, new TypeReference<Map<String, Object>>() {
});
@@ -182,5 +193,24 @@ class GraphQlArgumentInstantiatorTests {
this.name = name;
}
}
static class PrimaryConstructorComplexInput {
final String name;
final Item item;
public PrimaryConstructorComplexInput(String name, Item item) {
this.name = name;
this.item = item;
}
public String getName() {
return this.name;
}
public Item getItem() {
return item;
}
}
}