Merge branch '6.2.x'
This commit is contained in:
@@ -1051,7 +1051,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
}
|
||||
int startIdx = paramPath.length() + 1;
|
||||
int endIdx = name.indexOf(']', startIdx);
|
||||
String nestedPath = name.substring(0, endIdx + 2);
|
||||
String nestedPath = ((name.length() > endIdx + 1) ? name.substring(0, endIdx + 2) : "");
|
||||
boolean quoted = (endIdx - startIdx > 2 && name.charAt(startIdx) == '\'' && name.charAt(endIdx - 1) == '\'');
|
||||
String key = (quoted ? name.substring(startIdx + 1, endIdx - 1) : name.substring(startIdx, endIdx));
|
||||
if (map == null) {
|
||||
@@ -1083,7 +1083,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
SortedSet<Integer> indexes = null;
|
||||
for (String name : valueResolver.getNames()) {
|
||||
if (name.startsWith(paramPath + "[")) {
|
||||
int endIndex = name.indexOf(']', paramPath.length() + 2);
|
||||
int endIndex = name.indexOf(']', paramPath.length() + 1);
|
||||
String rawIndex = name.substring(paramPath.length() + 1, endIndex);
|
||||
int index = Integer.parseInt(rawIndex);
|
||||
indexes = (indexes != null ? indexes : new TreeSet<>());
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.samples.spr;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||
|
||||
@SpringJUnitWebConfig(ServletRequestDataBinderIntegrationTests.SpringWebKeyValueController.class)
|
||||
class ServletRequestDataBinderIntegrationTests {
|
||||
|
||||
@Test // gh-34043
|
||||
void postMap(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/map")
|
||||
.param("someMap[a]", "valueA")
|
||||
.param("someMap[b]", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postArray(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/array")
|
||||
.param("someArray[0]", "valueA")
|
||||
.param("someArray[1]", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test // gh-34121
|
||||
void postArrayWithEmptyIndex(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/array")
|
||||
.param("someArray[]", "valueA")
|
||||
.param("someArray[]", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postArrayWithoutIndex(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/array")
|
||||
.param("someArray", "valueA")
|
||||
.param("someArray", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postList(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/list")
|
||||
.param("someList[0]", "valueA")
|
||||
.param("someList[1]", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test // gh-34121
|
||||
void postListWithEmptyIndex(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/list")
|
||||
.param("someList[]", "valueA")
|
||||
.param("someList[]", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postListWithoutIndex(WebApplicationContext wac) throws Exception {
|
||||
MockMvc mockMvc = webAppContextSetup(wac).build();
|
||||
mockMvc.perform(post("/list")
|
||||
.param("someList", "valueA")
|
||||
.param("someList", "valueB"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("valueB"));
|
||||
}
|
||||
|
||||
record PayloadWithMap(Map<String, String> someMap) {}
|
||||
|
||||
record PayloadWithArray(String[] someArray) {}
|
||||
|
||||
record PayloadWithList(List<String> someList) {}
|
||||
|
||||
@RestController
|
||||
@SuppressWarnings("unused")
|
||||
static class SpringWebKeyValueController {
|
||||
|
||||
@PostMapping("/map")
|
||||
String postMap(@ModelAttribute("payload") PayloadWithMap payload) {
|
||||
return payload.someMap.get("b");
|
||||
}
|
||||
|
||||
@PostMapping("/array")
|
||||
String postArray(@ModelAttribute("payload") PayloadWithArray payload) {
|
||||
return payload.someArray[1];
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
String postList(@ModelAttribute("payload") PayloadWithList payload) {
|
||||
return payload.someList.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -241,6 +241,10 @@ public class ServletRequestDataBinder extends WebDataBinder {
|
||||
|
||||
protected @Nullable Object getRequestParameter(String name, Class<?> type) {
|
||||
Object value = this.request.getParameterValues(name);
|
||||
if (value == null && !name.endsWith ("[]") &&
|
||||
(List.class.isAssignableFrom(type) || type.isArray())) {
|
||||
value = this.request.getParameterValues(name + "[]");
|
||||
}
|
||||
return (ObjectUtils.isArray(value) && Array.getLength(value) == 1 ? Array.get(value, 0) : value);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user