Search code examples
javaspringspring-mvcspring-restcontrollerspring-rest

Is it possible to split request params in Spring controllers?


I have a request like:

example.com/search?sort=myfield1,-myfield2,myfield3

I would like to split those params to bind a List<String> sort in my controller or List<SortParam> where SortParam is the class with fields like: name (String) and ask (boolean).

So the final controller would look like this:

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> search(@RequestParam List<String> sort) {

    //...
}

or

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> search(@RequestParam List<SortParam> sort) {

    //...
}

Is there a way to make it?

UPDATE:

The standard way of passing parameters does not satisfy my requirements. I.e. I cannot use sort=myfield1&sort=-myfield2&sort=myfield3. I have to use comma separated names.
Also, I do understand that I can accept @RequestParam String sort in my controller and then split the string inside the controller like sort.split(",") but it also doesn't solve the above problem.


Solution

  • Yes, you can certainly do that, you're almost there.

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ResponseEntity<MyResponse> participants(@RequestParam("sort") List<String> sort) {
    
        //...
    }
    

    You should now be able to call your service like this (if search is located at your root, otherwise adapt according to your situation):

    curl "localhost:8080/search?sort=sortField1&sort=sortField2&sort=sortField3"
    

    Hope this helps!

    EDIT Sorry, I have read your comments and what you need is clear to me now. I have created a workaround for you that is almost what you want I think.

    So first a SortParams class:

    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class SortParams {
      private List<SortParam> sortParamList;
    
      public SortParams(String commaSeparatedString) {
        sortParamList = Arrays.stream(commaSeparatedString.split(","))
          .map(p -> SortParam.valueOf(p))
          .collect(Collectors.toList());
      }
    
      public List<SortParam> getSortParamList() {
        return this.sortParamList;
      }
    
      public enum SortParam {
        FOO, BAR, FOOBAR;
      }
    }
    

    Then your controller could look like this:

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ResponseEntity<List<SortParams.SortParam>> search(@RequestParam("sort") SortParams sort) {
        return ResponseEntity.ok(sort.getSortParamList());
    }
    

    Now your SortParams object has a list of SortParam:

    curl "localhost:8080/search?sort=FOO,BAR"
    
    ["FOO","BAR"]
    

    Would something like this fit what you're looking for?