Znheb
Znheb

Reputation: 121

How to disable spring boot parameter split

We have many @RestController receiving phrases in common language written by users. Phrases can be very long and contains punctuation, like periods and, of course, commas.

Simplified controller example:

@RequestMapping(value = "/countphrases", method = RequestMethod.PUT)
public String countPhrases(
    @RequestParam(value = "phrase", required = false) String[] phrase) {

  return "" + phrase.length;
}

Spring boot default behaviour is to split parameters values at comma, so the previous controller called with this url:

[...]/countphrases?phrase=john%20and%20me,%20you%and%her

Will return "2" istead of "1" like we want. In fact with the comma split the previous call is equivalent to:

[...]/countphrases?phrase=john%20and%20me&phrase=you%and%her

We work with natural language and we need to analyze phrases exactly how the users wrote them and to know exactly how many they wrote.

We tried this solution: https://stackoverflow.com/a/42134833/1085716 after adapting it to our spring boot version (2.0.5):

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // we hoped this code could remove the "split strings at comma"
        registry.removeConvertible(String.class, Collection.class);
    }
}

But it doesn't work.

Anyone know how to globally remove the "spring boot split string parameters at comma" behaviour in spring boot 2.0.5?

Upvotes: 3

Views: 2073

Answers (2)

eadjei
eadjei

Reputation: 2106

Replacing your formatter registry with a completely new list could make you loose some needed default formatters that would come with the framework. This will also disable all String-To-Collections parsing for the entire application, on every endpoint, such that if you want to a request filter such as the following at another endpoint, it won't work:

identifiers = 12,34,45,56,67

Solution: Just change your delimiter into something else... # or ; or $

identifiers = 12;23;34;45;56

This is what I have been doing, so I don't mess with all the goodies in the formatter registry.

Upvotes: 1

Znheb
Znheb

Reputation: 121

I find the solution. To override a default conversion we must add a new one. If we remove the old one only it doesn't work.

The correct (example) code should be:

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.removeConvertible(String.class, String[].class);
        registry.addConverter(String.class, String[].class, noCommaSplitStringToArrayConverter());
    }

    @Bean
    public Converter<String, String[]> noCommaSplitStringToArrayConverter() {
        return new Converter<String, String[]>() {
            @Override
            public String[] convert(String source) {
                String[] arrayWithOneElement = {source};
                return arrayWithOneElement;
            }
        };
    }
}

This way any controller like the one in the main question will not split parameters values:

  • [...]/countphrases?phrase=a,b will return 1 (and fq=["a,b"])
  • [...]/countphrases?phrase=a,b&phrase=c,d will return 2 (and fq=["a,b", "c,d"])

Upvotes: 5

Related Questions