Skip to content

Commit 0f38c28

Browse files
committed
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
1 parent 3505c4b commit 0f38c28

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ServletRequestDataBinderIntegrationTests.java

-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22-
import org.junit.jupiter.api.Disabled;
2322
import org.junit.jupiter.api.Test;
2423

2524
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
@@ -57,7 +56,6 @@ void postArray(WebApplicationContext wac) throws Exception {
5756
.andExpect(content().string("valueB"));
5857
}
5958

60-
@Disabled("see gh-34121")
6159
@Test // gh-34121
6260
void postArrayWithEmptyIndex(WebApplicationContext wac) throws Exception {
6361
MockMvc mockMvc = webAppContextSetup(wac).build();
@@ -88,7 +86,6 @@ void postList(WebApplicationContext wac) throws Exception {
8886
.andExpect(content().string("valueB"));
8987
}
9088

91-
@Disabled("see gh-34121")
9289
@Test // gh-34121
9390
void postListWithEmptyIndex(WebApplicationContext wac) throws Exception {
9491
MockMvc mockMvc = webAppContextSetup(wac).build();

spring-web/src/main/java/org/springframework/web/bind/ServletRequestDataBinder.java

+4
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ public final Object resolveValue(String name, Class<?> paramType) {
244244
@Nullable
245245
protected Object getRequestParameter(String name, Class<?> type) {
246246
Object value = this.request.getParameterValues(name);
247+
if (value == null && !name.endsWith ("[]") &&
248+
(List.class.isAssignableFrom(type) || type.isArray())) {
249+
value = this.request.getParameterValues(name + "[]");
250+
}
247251
return (ObjectUtils.isArray(value) && Array.getLength(value) == 1 ? Array.get(value, 0) : value);
248252
}
249253

spring-web/src/test/java/org/springframework/web/bind/ServletRequestDataBinderTests.java

+26
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,32 @@ void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() {
9393
assertThat(target.isPostProcessed()).isFalse();
9494
}
9595

96+
@Test
97+
public void testFieldWithArrayIndex() {
98+
TestBean target = new TestBean();
99+
ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
100+
binder.setIgnoreUnknownFields(false);
101+
102+
MockHttpServletRequest request = new MockHttpServletRequest();
103+
request.addParameter("stringArray[0]", "ONE");
104+
request.addParameter("stringArray[1]", "TWO");
105+
binder.bind(request);
106+
assertThat(target.getStringArray()).containsExactly("ONE", "TWO");
107+
}
108+
109+
@Test
110+
public void testFieldWithEmptyArrayIndex() {
111+
TestBean target = new TestBean();
112+
ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
113+
binder.setIgnoreUnknownFields(false);
114+
115+
MockHttpServletRequest request = new MockHttpServletRequest();
116+
request.addParameter("stringArray[]", "ONE");
117+
request.addParameter("stringArray[]", "TWO");
118+
binder.bind(request);
119+
assertThat(target.getStringArray()).containsExactly("ONE", "TWO");
120+
}
121+
96122
@Test
97123
void testFieldDefault() {
98124
TestBean target = new TestBean();

0 commit comments

Comments
 (0)