167

I'm sending some parameters from a form in this way:

myparam[0]     : 'myValue1'
myparam[1]     : 'myValue2'
myparam[2]     : 'myValue3'
otherParam     : 'otherValue'
anotherParam   : 'anotherValue' 
...

I know I can get all the params in the controller method by adding a parameter like

public String controllerMethod(@RequestParam Map<String, String> params){
    ....
}

I want to bind the parameters myParam[] (not the other ones) to a list or array (anything that keeps the index order), so I've tried with a syntax like:

public String controllerMethod(@RequestParam(value="myParam") List<String> myParams){
    ....
}

and

public String controllerMethod(@RequestParam(value="myParam") String[] myParams){
    ....
}

but none of them are binding the myParams. Even when I add a value to the map it is not able to bind the params:

public String controllerMethod(@RequestParam(value="myParam") Map<String, String> params){
    ....
}

Is there any syntax to bind some params to a list or array without having to create an object as @ModelAttribute with a list attribute in it?

Thanks

Javi
  • 19,387
  • 30
  • 102
  • 135
  • I don't think this is possible. The code in `HandlerMethodInvoker.resolveRequestParam` only ever gets the first value – skaffman Jan 04 '11 at 17:16
  • 10
    (*Spring Boot*): Is about `method = RequestMethod.GET` or `method = RequestMethod.POST`? If `.GET` `@RequestParam List groupVal` fulfilled from `?groupVal=kkk,ccc,mmm` successfully (*Spring Boot*) – basil Aug 06 '16 at 13:45

7 Answers7

123

Or you could just do it that way:

public String controllerMethod(@RequestParam(value="myParam[]") String[] myParams){
    ....
}

That works for example for forms like this:

<input type="checkbox" name="myParam[]" value="myVal1" />
<input type="checkbox" name="myParam[]" value="myVal2" />

This is the simplest solution :)

Bernhard
  • 1,231
  • 2
  • 8
  • 3
109

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.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • 1
    there may be problems with the order (which is very important to keep in my case) because I send the parameters by serializing a form and sending i with ajax. I'll use the "traditional" @ModelAttribute way. – Javi Jan 05 '11 at 08:07
  • Would you happen to know how to construct a URI with this sort mapping with UriTemplate, or some other means? (for a client of this sort of resource). – Chomeh May 04 '15 at 04:24
  • Answering my own question, it apears the spring UriTemplate doesn't support RFC6570, use the damnhandy implementation: http://stackoverflow.com/questions/14153036/how-to-send-array-with-spring-resttemplate – Chomeh May 04 '15 at 06:54
39

Subscribing what basil said in a comment to the question itself, if method = RequestMethod.GET you can use @RequestParam List<String> groupVal.

Then calling the service with the list of params is as simple as:

API_URL?groupVal=kkk,ccc,mmm
dube
  • 4,898
  • 2
  • 23
  • 41
Juangui Jordán
  • 6,091
  • 2
  • 35
  • 31
25

Just complementing what Donal Fellows said, you can use List with @RequestParam

public String controllerMethod(@RequestParam(value="myParam") List<ObjectToParse> myParam){
....
}

Hope it helps!

Jorge Peres
  • 377
  • 3
  • 4
10

One way you could accomplish this (in a hackish way) is to create a wrapper class for the List. Like this:

class ListWrapper {
     List<String> myList; 
     // getters and setters
}

Then your controller method signature would look like this:

public String controllerMethod(ListWrapper wrapper) {
    ....
}

No need to use the @RequestParam or @ModelAttribute annotation if the collection name you pass in the request matches the collection field name of the wrapper class, in my example your request parameters should look like this:

myList[0]     : 'myValue1'
myList[1]     : 'myValue2'
myList[2]     : 'myValue3'
otherParam    : 'otherValue'
anotherParam  : 'anotherValue'
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
driangle
  • 11,601
  • 5
  • 47
  • 54
  • Well this is almost the same as using @ModelAttribute, the only difference is that the param is not annotated. I wanted to avoid @ModelAttribute just because I didn't want to create a wrapper. I read somewhere in stackoverflow (I can't remember where exactly) that if you add a param in the controller method without @ModelAttribute annotation (and it wasn't a special object like HttpRequest, HttpResponse...) the framework treat it as if it were annotated with @ModelAttribute. So if that was true this is exactly as having @ModelAttribute. But thanks for your answer. – Javi Jan 06 '11 at 19:41
  • @driangle I have a similar case but I have 2 Sets of and I wrap them both in one object. However after I do it I can no longer use comma separated syntax to assign values to my sets. If I do ?idsType1=QWE,RTY,UIO I am getting one element with "QWE,RTY,UIO" as value. SpringBoot 2.1.1.RELEASE, Java 8 openjdk – Marcin K. Dec 13 '22 at 09:16
6

It wasn't obvious to me that although you can accept a Collection as a request param, but on the consumer side you still have to pass in the collection items as comma separated values.

For example if the server side api looks like this:

@PostMapping("/post-topics")
public void handleSubscriptions(@RequestParam("topics") Collection<String> topicStrings) {

    topicStrings.forEach(topic -> System.out.println(topic));
}

Directly passing in a collection to the RestTemplate as a RequestParam like below will result in data corruption

public void subscribeToTopics() {

    List<String> topics = Arrays.asList("first-topic", "second-topic", "third-topic");

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForEntity(
            "http://localhost:8088/post-topics?topics={topics}",
            null,
            ResponseEntity.class,
            topics);
}

Instead you can use

public void subscribeToTopics() {

    List<String> topicStrings = Arrays.asList("first-topic", "second-topic", "third-topic");
    String topics = String.join(",",topicStrings);

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForEntity(
            "http://localhost:8088/post-topics?topics={topics}",
            null,
            ResponseEntity.class,
            topics);
}

The complete example can be found here, hope it saves someone the headache :)

Péter Veres
  • 955
  • 1
  • 10
  • 25
-10

Change hidden field value with checkbox toggle like below...

HTML:

<input type='hidden' value='Unchecked' id="deleteAll" name='anyName'>
<input type="checkbox"  onclick="toggle(this)"/> Delete All

Script:

function toggle(obj) {`var $input = $(obj);
    if ($input.prop('checked')) {

    $('#deleteAll').attr( 'value','Checked');

    } else {

    $('#deleteAll').attr( 'value','Unchecked');

    }

}
Khomeni
  • 1
  • 1