Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@RequestParam array mapping issues

Tags:

java

spring

I'm doing a REST service with Spring MVC framework.

I have a method:

@RequestMapping("/rest/{tableName}", method = RequestMethod.GET)
public @ResponseBody CustomObject query(
    @PathVariable("tableName") String tableName, 
    @RequestParam(value="columns", required=false) String[] columns,
    @RequestParam(value="filter", required=false) String[][] filters) {
...
}

Well, I want filters to be a bidimensional array which an specific structure:

If I do a request with this url /rest/table?filter=filter1,filter2&filter=filter3 I have then filters = {{filter1, filter2}, {filter3}}

If I do with: /rest/table?filter=filter1&filter=filter2 I have: filters = {{filter1},{filter2}}

My question is...

why if I call:/rest/table?filter=filter1,filter2 I get: filters = {{filter1},{filter2}} and not: filters = {{filter1,filter2}}?

Is there any way for get the last array instead of the first in that situation?

like image 392
Reik Val Avatar asked May 16 '14 13:05

Reik Val


2 Answers

Sending lists of items in the URL is tricky. In general, the request

/rest/table?filter=A&filter=B

and

/rest/table?filter=A,B

will both get parsed as if A and B are individual parameters. This is because Spring's default WebDataBinder is configured to split parameters lists on commas. You can disable this default configuration by adding some binder initialization code to your controller.

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(
        String[].class,
        new StringArrayPropertyEditor(null)); 
}

Now the data binding process for parameter lists coming in over HTTP will not be split on the comma, and be interpreted as separate items. This will likely produce the behavior you're looking for, so that comma-delimited parameter lists will be treated as a single array parameter rather than N separate single-item array parameters.

like image 199
Misha Avatar answered Sep 30 '22 03:09

Misha


Instead of only disabling the usage of comma as separator, for overriding the use of a comma delimiter with pipe I did the following:

1 - Created a class that extends PropertyEditorSupport setting the delimiter as pipe.

public class StringListPropertyEditor extends PropertyEditorSupport {

    public static final String DEFAULT_SEPARATOR = "\\|";

    @Override
    public void setAsText(String text) throws IllegalArgumentException {

        List<String> theList = Arrays.asList(text.split(DEFAULT_SEPARATOR));

        setValue(theList);

    }


}

2 - Created a InitBinder at my controller which register my PropertyEditor as CustomEditor

@InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(List.class, new StringListPropertyEditor());
    }
like image 26
Shell_Leko Avatar answered Sep 30 '22 04:09

Shell_Leko