Fix ServletRequestDataBinder ctor binding with []-indexed query params

This change ensures that a request containing query parameters in the
array format `someArray[]=value` can be bound into a simple array in
constructors, even for cases where the array values don't have nested
properties.

The value resolver is directly called in the constructor case, before
any mutable properties are considered or even cleared (see
`WebDataBinder#adaptEmptyArrayIndices` method). As a result, we need to
accommodate the possibility that the request stores array elements under
the `name[]` key rather than `name`. This change attempts a secondary
lookup with the `[]` suffix if the type is a list or array, and the key
doesn't include an index.

Closes gh-34121
This commit is contained in:
Simon Baslé
2024-12-27 10:30:35 +01:00
parent 3505c4bcad
commit 0f38c28e91
3 changed files with 30 additions and 3 deletions

View File

@@ -93,6 +93,32 @@ class ServletRequestDataBinderTests {
assertThat(target.isPostProcessed()).isFalse();
}
@Test
public void testFieldWithArrayIndex() {
TestBean target = new TestBean();
ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
binder.setIgnoreUnknownFields(false);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("stringArray[0]", "ONE");
request.addParameter("stringArray[1]", "TWO");
binder.bind(request);
assertThat(target.getStringArray()).containsExactly("ONE", "TWO");
}
@Test
public void testFieldWithEmptyArrayIndex() {
TestBean target = new TestBean();
ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
binder.setIgnoreUnknownFields(false);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("stringArray[]", "ONE");
request.addParameter("stringArray[]", "TWO");
binder.bind(request);
assertThat(target.getStringArray()).containsExactly("ONE", "TWO");
}
@Test
void testFieldDefault() {
TestBean target = new TestBean();