Skip to content

Commit 75d5d4b

Browse files
committed
Allow binding raw map to Map<String,?>
Closes gh-554
1 parent c16521c commit 75d5d4b

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,9 @@ private Map<?, Object> bindMapToMap(
245245
ArgumentsBindingResult bindingResult) {
246246

247247
ResolvableType valueType = targetType.asMap().getGeneric(1);
248-
Class<?> valueClass = valueType.resolve();
249-
if (valueClass == null) {
250-
bindingResult.rejectArgumentValue(name, null, "unknownType", "Unknown Map value type");
251-
return Collections.emptyMap(); // Keep going, to record more errors
248+
Class<?> valueClass = valueType.resolve(Object.class);
249+
if (valueClass == Object.class) {
250+
return rawMap;
252251
}
253252

254253
Map<String, Object> map = CollectionFactory.createMap(targetClass, rawMap.size());

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ void primaryConstructorBindingErrorWithNestedBeanList() {
318318
}
319319

320320
@Test
321-
void primaryConstructorWithMapArgument() throws Exception {
321+
void primaryConstructorWithItemMapArgument() throws Exception {
322322

323323
Object result = bind(
324324
"{\"map\":{\"item1\":{\"name\":\"Jason\",\"age\":\"21\"},\"item2\":{\"name\":\"James\",\"age\":\"22\"}}}",
@@ -336,6 +336,25 @@ void primaryConstructorWithMapArgument() throws Exception {
336336
assertThat(item2.getAge()).isEqualTo(22);
337337
}
338338

339+
@Test // gh-554
340+
void primaryConstructorWithRawMapArgument() throws Exception {
341+
342+
Object result = bind(
343+
"{\"map\":{\"item1\":{\"name\":\"Jason\",\"age\":\"21\"},\"item2\":{\"name\":\"James\",\"age\":\"22\"}}}",
344+
ResolvableType.forClass(PrimaryConstructorRawMapBean.class));
345+
346+
assertThat(result).isNotNull().isInstanceOf(PrimaryConstructorRawMapBean.class);
347+
Map<String, ?> map = ((PrimaryConstructorRawMapBean) result).getMap();
348+
349+
Map<String, Object> item1 = (Map<String, Object>) map.get("item1");
350+
assertThat(item1).containsEntry("name", "Jason");
351+
assertThat(item1).containsEntry("age", "21");
352+
353+
Map<String, Object> item2 = (Map<String, Object>) map.get("item2");
354+
assertThat(item2).containsEntry("name", "James");
355+
assertThat(item2).containsEntry("age", "22");
356+
}
357+
339358
@Test // gh-447
340359
@SuppressWarnings("unchecked")
341360
void primaryConstructorWithGenericObject() throws Exception {
@@ -476,6 +495,20 @@ public Map<String, Item> getMap() {
476495
}
477496

478497

498+
static class PrimaryConstructorRawMapBean {
499+
500+
private final Map<String, ?> map;
501+
502+
public PrimaryConstructorRawMapBean(Map<String, ?> map) {
503+
this.map = map;
504+
}
505+
506+
public Map<String, ?> getMap() {
507+
return this.map;
508+
}
509+
}
510+
511+
479512
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
480513
static class PrimaryConstructorOptionalItemBean {
481514

0 commit comments

Comments
 (0)