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

3

7

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.

Funda answered 8/2, 2017 at 18:11 Comment(1)
Some solutions are here #4999248Faythe
B
8

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);
  }
}
Brassie answered 9/2, 2017 at 10:57 Comment(1)
Can you suggest a similar solution for an individual endpoint?Marquise
D
2

this is a shorter version, THANKS to @Strelok

import java.util.Collection;
import java.util.Collections;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.removeConvertible(String.class, Collection.class);
        registry.addConverter(String.class, Collection.class, Collections::singletonList);
    }
}
Dah answered 11/12, 2019 at 17:18 Comment(0)
S
1

I managed to solve the problem by applying the following: how-to-prevent-parameter-binding-from-interpreting-commas-in-spring-3-0-5

The trick is done by the following lines of code

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

More information: Why escaped comma is the delimiter for @RequestParam List?

Signal answered 4/3, 2022 at 22:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.