Binding a List in @Requestparam

Binding a list in @RequestParam

Arrays in @RequestParam are used for binding several parameters of the same name:

myparam=myValue1&myparam=myValue2&myparam=myValue3

If you need to bind @ModelAttribute-style indexed parameters, I guess you need @ModelAttribute anyway.

Is it impossible to have a @RequestParam as a List?

The most common & standard way to pass a list of values as URL parameters is to repeat them i.e.

http://rentacar.com/api/v1/search?make=audi&model=A8&type=6&type=11&type=12&color=RED&color=GREY

Now the question is to handle such input in Spring MVC REST endpoint? Lets assume you are developing a search api to find cars available to rent; this is how you will do it:

public List<Vehicle> search(@RequestParam(value="make", required=false) String make, @RequestParam(value="model", required=false) String model, @RequestParam(value="type", required=false) List<String> types, @RequestParam(value="color", required=false) List<String> colors) {
....
}

https://medium.com/@rasheedamir/spring-mvc-how-to-pass-list-of-values-as-url-parameters-5d57dcac8457

Spring - Binding list with request param

So, i find a solution to fix my issue :

In my query, I set my query to : {"status":"ACTIVE,INACTIVE"} instead of {"status":["ACTIVE","INACTIVE"]}

Binding a list in @RequestParam includes square brackets

You don't need to use [] syntax to pass arrays (or lists).

Try to execute your request this way:

/countRequests?languages=EN,IT

This way Spring MVC should bind your parameter correctly. Take a try.

Another way is to use this syntax:

/countRequests?languages[]=EN&languages[]=IT

In Spring, how do I bind a list of integers to a RequestParam?

The problem you are facing is that java has type erasure. So at runtime a List<Integer> is equivalent than a List<String> and spring has no way of knowing you want Integers into your list.

A work around might be using a integer array instead of a List of integers.

@RequestMapping("/delete.x")
public @ResponseBody Map<String, Object> delete(HttpServletRequest request,
@RequestParam("ids[]") Integer[] ids) {

Spring MVC @RequestParam a list of objects

Request parameters are a Multimap of String to String. You cannot pass a complex object as request param.

But if you just pass the username that should work - see how to capture multiple parameters using @RequestParam using spring mvc?

@RequestParam("users") List<String> list

But I think it would be better to just use the request body to pass information.

Spring MVC: Issues Binding Request Parameters to a Generic List

You can implement your own HandlerMethodArgumentResolver like this:

@Component
public class HolderMethodArgumentResolver implements HandlerMethodArgumentResolver {

@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return Holder.class.isAssignableFrom(methodParameter.getParameterType());
}

@Override
public Holder resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
Class<?> genericClass = (Class<?>) ((ParameterizedType) methodParameter.getGenericParameterType()).getActualTypeArguments()[0];
if (Integer.class.isAssignableFrom(genericClass)) {
String[] values = nativeWebRequest.getParameterValues("items");
List<Integer> convertedValues = Stream.of(values).map(Integer::valueOf).collect(Collectors.toList());
return new Holder<>(convertedValues);
}
if (String.class.isAssignableFrom(genericClass)) {
String[] values = nativeWebRequest.getParameterValues("items");
return new Holder<>(Arrays.asList(values));
}
throw new IllegalArgumentException("Generic type " + genericClass + " doesn't support");
}

}

And after that you can define in contoller different methods:

    @GetMapping("/test")
public String test(Holder<Integer> holder) {
List<Integer> items = holder.getItems();

System.out.println(items.size());
System.out.println(items);
if (!items.isEmpty()) {
System.out.println(items.get(0).getClass());
}
return "test";
}

@GetMapping("/test2")
public String test2(Holder<String> holder) {
List<String> items = holder.getItems();

System.out.println(items.size());
System.out.println(items);
if (!items.isEmpty()) {
System.out.println(items.get(0).getClass());
}
return "test2";
}

How/Why does parameter binding work without @RequestParam?

Who is in charge of solving if you do not place any annotation on parameters?

It is this RequestParamMethodArgumentResolver the documentation says:

Resolves method arguments annotated with @RequestParam, arguments of
type MultipartFile in conjunction with Spring's MultipartResolver
abstraction, and arguments of type javax.servlet.http.Part in
conjunction with Servlet 3.0 multipart requests. This resolver can
also be created in default resolution mode in which simple types (int,
long, etc.) not annotated with @RequestParam are also treated as
request parameters with the parameter name derived from the argument
name. If the method parameter type is Map, the name specified in the
annotation is used to resolve the request parameter String value. The
value is then converted to a Map via type conversion assuming a
suitable Converter or PropertyEditor has been registered. Or if a
request parameter name is not specified the
RequestParamMapMethodArgumentResolver is used instead to provide
access to all request parameters in the form of a map.

A WebDataBinder is invoked to apply type conversion to resolved
request header values that don't yet match the method parameter type.

So that is the reason why it works.

RequestParam with map is unnecessarily binding other request params in GET request

As mentioned in the comments, you can't exclude params for the @RequestParam map.

Do your client have the option to send those params with the body as a json object instead of as request parameters? A request body isn't normally sent in GET Requests, but you could do it. Then you would change @RequestParam<String, String> map) to @RequestBody Map<String, String> map)



Related Topics



Leave a reply



Submit