Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Spring MVC from interpreting commas when converting to a Collection in Spring Boot?

We basically have the same problem as this question poses, but for lists and additionally, we are looking for a global solution.

Currently we have a REST call that is defined like this:

@RequestMapping
@ResponseBody
public Object listProducts(@RequestParam(value = "attributes", required = false) List<String> attributes) {

The call works fine and the list attributes will contain two elements "test1:12,3" and "test1:test2" when called like this:

product/list?attributes=test1:12,3&attributes=test1:test2

However, the list attributes will also contain two elements, "test1:12" and "3" when called as follows:

product/list?attributes=test1:12,3

The reason for this is, that in the first case, Spring will use a ArrayToCollectionConverter in the first case. In the second case it will use a StringToCollectionConverter which will split the argument using "," as a separator.

How can I configure Spring Boot to ignore the comma in the parameter? The solution should be global if possible.

What we have tried:

This question does not work for us, because we have a List instead of an array. Besides, this would be a controller-local solution only.

I also tried to add this configuration:

@Bean(name="conversionService")
public ConversionService getConversionService() {
    ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
    bean.setConverters(Collections.singleton(new CustomStringToCollectionConverter()));
    bean.afterPropertiesSet();
    return bean.getObject();
}

where CustomStringToCollectionConverter is a copy of the Spring StringToCollectionConverter, but without the splitting, however, the Spring converter still gets called preferentially.

On a hunch, I also tried "mvcConversionService" as a bean name, but that did not change anything either.

like image 732
ircecho Avatar asked Feb 08 '17 18:02

ircecho


2 Answers

You can remove the StringToCollectionConverter and replace it with your own in WebMvcConfigurerAdapter.addFormatters(FormatterRegistry registry) method:

Something like this:

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
  @Override
  public void addFormatters(FormatterRegistry registry) {
    registry.removeConvertible(String.class,Collection.class);
    registry.addConverter(String.class,Collection.class,myConverter);
  }
}
like image 74
Strelok Avatar answered Nov 15 '22 08:11

Strelok


For me it worked fine even without the line for adding a new converter but because @Strelok did not provide an example how to write a new converter here is a full solution:

@Configuration
class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.removeConvertible(String.class, Collection.class);
        registry.addConverter(String.class, Collection.class, noCommaSplitStringToCollectionConverter());
    }

    public Converter<String, Collection> noCommaSplitStringToCollectionConverter() {
        return Collections::singletonList;
    }

}

My version is a modified and update one of a string to array converter you can find here: How to disable spring boot parameter split

like image 42
Neonchen Avatar answered Nov 15 '22 07:11

Neonchen