Affects: 2.5.2

Many http clients pass an array to queryString in this form: ?attributes[]=field1&attributes[]=field2

I'm trying to get Controller to work with this format through RequestParam:

@RestController
public class FooController {

   @RequestMapping(method = RequestMethod.GET,
    value = "/foo",
    produces = "application/json")
   ResponseEntity<FooDto> getFoo(@RequestParam(value = "attributes", required = false) List<String> attributes) {
   }
}

However, when executing a request, null is passed to the controller method as the attributes value.

I found that the "RequestParamMethodArgumentResolver.resolveName" method receives "attributes" as the value of the parameter name, while this parameter is stored in the request object using the key "attributes[]". Therefore, the argument of the controller method is null, because resolver cannot find a match.

How would you like to add such support to RequestParamMethodArgumentResolver? The code could look something like this:

@Override
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
      if (
          (
              parameterTypeIs(List.class, parameter) || parameterTypeIs(Set.class, parameter)
          )
          && nameIsIndexParameter(name, request)) {
        return super.resolveName(name + "[]", parameter, request);

      }
      return super.resolveName(name, parameter, request);
    }

    private boolean parameterTypeIs(Class<?> parameterType, MethodParameter parameter) {
      return parameterType.isAssignableFrom(parameter.getParameterType());
    }

    private boolean nameIsIndexParameter(String name, NativeWebRequest request) {
      return request.getParameterMap().containsKey(name + "[]");
    }

In my project, I replaced the built-in RequestParamMethodArgumentResolver with a custom one. An example can be found in the description of the question on stackoverflow

Comment From: snicoll

Many http clients pass an array to queryString in this form

Do they? I can see this being used in PHP but that's an implementation detail that's not backed by anything I am aware of in a spec. If you need to pass multiple values, you should use the attribute as requested and let the server rebuild the list for you.

Comment From: panovst

then why do you support this format here?

Special DataBinder for data binding from web request parameters to JavaBean objects

org.springframework.web.bind.WebDataBinder#adaptEmptyArrayIndices

Check for property values with names that end on "[]". This is used by some clients for array syntax without an explicit index value. If such values are found, drop the brackets to adapt to the expected way of expressing the same for data binding purposes.

Comment From: snicoll

I wasn't aware we did. That's a question for @rstoyanchev then

See https://github.com/spring-projects/spring-framework/issues/25836#issuecomment-704927342

Comment From: panovst

Our situation is further complicated by the following: we use the open api to describe the contract, and the openapi-generator to generate the client and controller interfaces.

this means that even if we consider this option (from the link to the issue that you provided)

fun getAllEntities(@RequestParam(name="types[]") types: List<String>) {}

there are two disadvantages to this solution: 1. we have to use the attributes[] format in the openapi itself 2. only clients sending "attributes[]=" will be able to work with this method

Comment From: rstoyanchev

Indeed I think this is the the equivalent of #25836 but for @RequestParam.