spring-projects / spring-projects/spring-framework
Array GET parameter using `[]` suffix is not work on Spring WebMVC
Open
Nobody has claimed this yet.
in: web
status: waiting-for-triage
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Problem
Array GET parameter using [] suffix is not work on Spring WebMVC .
- using GET method
- using ModelAttribute to resolve handler method argument
- using
[]suffix parameter and multipe values
Versions
- Spring Boot 3.5.7
- Spring Framework 6.2.12
Reproduction Code
production code
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.RestController
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
// ===== Form Class (Constructor Binding) =====
data class SomeForm(
val names: List<String>? = null
)
// ===== Controller =====
@RestController
class DemoController {
@GetMapping("/some")
fun some(@ModelAttribute form: SomeForm): Map<String, Any> {
val names = form.names ?: emptyList()
return mapOf(
"names" to names,
"size" to names.size,
"request" to "GET /some with names[] parameter"
)
}
}
test code
package com.example.demo
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.get
@WebMvcTest(DemoController::class)
class DemoControllerTest {
@Autowired
private lateinit var mockMvc: MockMvc
@Test
fun `array parameter binding with brackets fails to bind multiple values`() {
// BUG: Only the first value is bound when using names[] notation
// Expected: names = ["1", "2"], size = 2
// Actual: names = ["1"], size = 1
mockMvc.get("/some") {
param("names[]", "1")
param("names[]", "2")
}.andDo {
print()
}.andExpect {
status { isOk() }
jsonPath("$.size") { value(2) } // This assertion should fail
jsonPath("$.names[0]") { value("1") }
jsonPath("$.names[1]") { value("2") } // names[1] doesn't exist
}
}
@Test
fun `array parameter binding without brackets works correctly`() {
// Control test: Without brackets, multiple values are bound correctly
mockMvc.get("/some") {
param("names", "1")
param("names", "2")
}.andDo {
print()
}.andExpect {
status { isOk() }
jsonPath("$.size") { value(2) }
jsonPath("$.names[0]") { value("1") }
jsonPath("$.names[1]") { value("2") }
}
}
@Test
fun `single value with brackets binds correctly`() {
// Verify behavior with single value
mockMvc.get("/some") {
param("names[]", "1")
}.andDo {
print()
}.andExpect {
status { isOk() }
jsonPath("$.size") { value(1) }
jsonPath("$.names[0]") { value("1") }
}
}
@Test
fun `empty parameters return empty list`() {
// Verify behavior with no parameters
mockMvc.get("/some")
.andDo {
print()
}.andExpect {
status { isOk() }
jsonPath("$.size") { value(0) }
jsonPath("$.names") { isArray() }
}
}
}
Related
- #26721
- #34305
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied DemoControllerTest and compare repeated names[] parameters with repeated names parameters while tracing @ModelAttribute binding in Spring WebMVC. The work is done when the bracketed form binds both values, the existing control and edge-case tests still pass, and the reported failing assertion succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100