Affects: \< Spring Boot 2.1.2.RELEASE>
I have a simple rest controller with the method the get requests mapped on:
@GetMapping("/cis_list")
public Map<String, CisFrontendDto> cisList(@RequestParam(value = "cis") List<String> cis) {
log.debug("#cisList: started with cisIds = {}", cis);
return cisService.findByIds(cis);
}
I try to pass string hello, world! as a single element of List
curl -X GET "http://127.0.0.1:8095/api/v3/facade/cis/cis_list?cis=hello%2C%20world!" -H "accept: /"
I have expected the list contains only one string but аs it turned the list contains two elements although the comma has been escaped in source request.
In this way there's not a difference between requests:
curl -X GET "http://127.0.0.1:8095/api/v3/facade/cis/cis_list?cis=hello%2C%20world!" -H "accept: /"
and
curl -X GET "http://127.0.0.1:8095/api/v3/facade/cis/cis_list?cis=hello,%20world!" -H "accept: /"
So, I'm not able to map parameters of HTTP GET requests to Java List if they contain escaped commas.
Comment From: rstoyanchev
This is due to the StringToCollectionConverter
which gets involved if there is 1 request parameter value and we have to convert from String
to List<String>
. When there are multiple values the ArrayToCollectionConverter
is used, so the behavior is specific to single values. It is a bit surprising I will admit, but we're unlikely to change this behavior at this time. Rather I can suggest that you remove the String
to Collection
conversion through the formatters callback in the WebMvcConfig.
Comment From: nschrader
Let's be honest, it's just broken. The parameter is sent with a percent escaped ,
(%2C) and according to RFC 3986, parameters need to be separated by an unescaped ,
. Things that belong together get ripped apart, although we have the information that they shouldn't.
(And the RFC even explicitly states that commas are allowed as parameter values as long as they are percent escaped.)
Comment From: helderhernandez
I managed to solve the problem by applying the following: - How to prevent parameter binding from interpreting commas in Spring 3.0.5? - How to prevent Spring MVC from interpreting commas when converting to a Collection in Spring Boot?
The trick is done by the following lines of code
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor(null));
}
My classes were as follows:
Clase Search (works as a wrapper)
public class Search {
private String[] search = new String[] {};
public Search() {
super();
}
public Search(String[] search) {
super();
this.search = search;
}
public String[] getSearch() {
return search;
}
public void setSearch(String[] search) {
this.search = search;
}
public List<String> toList() {
return Arrays.asList(this.search);
}
@Override
public String toString() {
return "Search [search=" + Arrays.toString(search) + "]";
}
}
Endpoint
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor(null));
}
@GetMapping("/search")
@ResponseStatus(HttpStatus.OK)
@ApiOperation(value = "Search providers")
//@formatter:off
@ApiImplicitParams({
@ApiImplicitParam(
name = "search",
allowMultiple = true,
dataType = "string",
paramType = "query",
value = "Search by field: description"
)
})
//@formatter:on
public List<String> search(Search search) {
System.out.println(search.toList().size());
search.toList().forEach(System.out::println);
//..... your code
}