@@ -71,7 +71,7 @@ public class GraphQlArgumentBinder {
7171
7272 private final BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor ();
7373
74- private List <Consumer <DataBinder >> dataBinderInitializers = new ArrayList <>();
74+ private final List <Consumer <DataBinder >> dataBinderInitializers = new ArrayList <>();
7575
7676
7777 public GraphQlArgumentBinder () {
@@ -160,7 +160,7 @@ public Object bind(
160160 // From Map
161161
162162 if (rawValue instanceof Map ) {
163- Object target = createValue ((Map <String , Object >) rawValue , targetClass , bindingResult , segments );
163+ Object target = createValue ((Map <String , Object >) rawValue , targetType , bindingResult , segments );
164164 return wrapAsOptionalIfNecessary (target , targetType );
165165 }
166166
@@ -204,6 +204,7 @@ private <T> Collection<T> createCollection(
204204 return Collections .emptyList ();
205205 }
206206
207+ ResolvableType elementType = collectionType .asCollection ().getGeneric (0 );
207208 Class <?> elementClass = collectionType .asCollection ().getGeneric (0 ).resolve ();
208209 if (elementClass == null ) {
209210 bindingResult .rejectValue (toArgumentPath (segments ), "unknownElementType" , "Unknown element type" );
@@ -218,7 +219,7 @@ private <T> Collection<T> createCollection(
218219 collection .add ((T ) rawValue );
219220 }
220221 else if (rawValue instanceof Map ) {
221- collection .add ((T ) createValueOrNull ((Map <String , Object >) rawValue , elementClass , bindingResult , segments ));
222+ collection .add ((T ) createValueOrNull ((Map <String , Object >) rawValue , elementType , bindingResult , segments ));
222223 }
223224 else {
224225 collection .add ((T ) convertValue (rawValue , elementClass , bindingResult , segments ));
@@ -230,7 +231,7 @@ else if (rawValue instanceof Map) {
230231
231232 @ Nullable
232233 private Object createValueOrNull (
233- Map <String , Object > rawMap , Class <?> targetType , BindingResult result , Stack <String > segments ) {
234+ Map <String , Object > rawMap , ResolvableType targetType , BindingResult result , Stack <String > segments ) {
234235
235236 try {
236237 return createValue (rawMap , targetType , result , segments );
@@ -242,11 +243,40 @@ private Object createValueOrNull(
242243
243244 @ SuppressWarnings ("unchecked" )
244245 private Object createValue (
245- Map <String , Object > rawMap , Class <?> targetType , BindingResult bindingResult ,
246+ Map <String , Object > rawMap , ResolvableType targetType , BindingResult bindingResult ,
246247 Stack <String > segments ) throws BindException {
247248
249+ Class <?> targetClass = targetType .resolve ();
250+ Assert .notNull (targetClass , "Unknown target class" );
251+
252+ if (Map .class .isAssignableFrom (targetClass )) {
253+ ResolvableType valueType = targetType .asMap ().getGeneric (1 );
254+ Class <?> valueClass = valueType .resolve ();
255+ if (valueClass == null ) {
256+ bindingResult .rejectValue (toArgumentPath (segments ), "unknownMapValueType" , "Unknown Map value type" );
257+ return Collections .emptyMap ();
258+ }
259+ Map <String , Object > map = CollectionFactory .createMap (targetClass , rawMap .size ());
260+ for (Map .Entry <String , Object > entry : rawMap .entrySet ()) {
261+ Object rawValue = entry .getValue ();
262+ segments .push ("[" + entry .getKey () + "]" );
263+ if (rawValue == null || valueType .isAssignableFrom (rawValue .getClass ())) {
264+ map .put (entry .getKey (), entry .getValue ());
265+ }
266+ else if (rawValue instanceof Map ) {
267+ map .put (entry .getKey (), createValueOrNull (
268+ (Map <String , Object >) rawValue , valueType , bindingResult , segments ));
269+ }
270+ else {
271+ map .put (entry .getKey (), convertValue (rawValue , valueClass , bindingResult , segments ));
272+ }
273+ segments .pop ();
274+ }
275+ return map ;
276+ }
277+
248278 Object target ;
249- Constructor <?> ctor = BeanUtils .getResolvableConstructor (targetType );
279+ Constructor <?> ctor = BeanUtils .getResolvableConstructor (targetClass );
250280
251281 // Default constructor + data binding via properties
252282
@@ -293,7 +323,7 @@ else if (isApproximableCollectionType(rawValue)) {
293323 }
294324 else if (rawValue instanceof Map ) {
295325 boolean isOptional = (paramTypes [i ] == Optional .class );
296- Class <?> type = ( isOptional ? methodParam .nestedIfOptional (). getNestedParameterType () : paramTypes [ i ] );
326+ ResolvableType type = ResolvableType . forMethodParameter ( methodParam .nestedIfOptional ());
297327 Object value = createValueOrNull ((Map <String , Object >) rawValue , type , bindingResult , segments );
298328 args [i ] = (isOptional ? Optional .ofNullable (value ) : value );
299329 }
0 commit comments