0

Hello Spring Developers

I have a spring-boot related issue, which I don't know how to resolve properly.

This issue is a direct consequence of spring's behaviour with query parameters: When a single query parameter contains the , character it will be split by that comma.

Example:

XXX?array=1,2,3 => ["1", "2", "3"]

When a query parameter - containing the , character - is defined multiple times, spring will not split every value by the comma.

Example:

XXX?array=1,2&array=3 => ["1,2", "3"]

Issue: Some of our query parameters may contain a , character.

Since spring does not behave like the RFC is stated I need a way to NOT split the query parameters by commas.

My Controller

@RestController
public class Controller {

    @GetMapping(path = "arrays", produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public List<String> getArrayQueryParameters(@RequestParam("array") String[] array) {
        return Arrays.asList(array);
    }
}

My Testcase

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Controller.class)
@AutoConfigureMockMvc
@EnableAutoConfiguration(exclude=SecurityAutoConfiguration.class)
public class ControllerMvcTest {

    @Autowired
    private MockMvc mvc;

    // This Test fails
    @Test
    void oneParameter() throws Exception {
        mvc.perform(get("/arrays?array=1,2,3,4,5")
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(1)))
            .andExpect(jsonPath("$[0]", is("1,2,3,4,5")));
    }

    @Test
    void parameterTwoTimes() throws Exception {
        mvc.perform(get("/arrays?array=1,2&array=3,4,5")
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(2)))
            .andExpect(jsonPath("$[0]", is("1,2")))
            .andExpect(jsonPath("$[1]", is("3,4,5")));
    }

    @Test
    void parameterThreeTimes() throws Exception {
        mvc.perform(get("/arrays?array=1,2&array=3&array=4,5")
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(3)))
            .andExpect(jsonPath("$[0]", is("1,2")))
            .andExpect(jsonPath("$[1]", is("3")))
            .andExpect(jsonPath("$[2]", is("4,5")));
    }
}

You can find an example github repo here: https://github.com/arolfes/RestArrayParametersSample

1 Answer 1

4

You can make query params not split by commas using @InitBinder and DataBinder.

Spring DataBinder uses StringToArrayConverter for converting String to String[], which behaves as you experienced. (Related source codes)

Classes annotated with @Controller or @ControllerAdvice can have methods with @InitBinder.

You can utilize registerCustomEditor() of DataBinder to applying PropertyEditor which not using the comma delimiter.

If you add this method for your ControllerServletRequest, the first test case will succeed. (I checked.)

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

As you can see, I intentionally give null for constructor of StringArrayPropertyEditor because the arg is delimiter, whose default value is ",". (Related source codes)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.