spring-projects / spring-projects/spring-framework

Array GET parameter using `[]` suffix is not work on Spring WebMVC

Open
#35,734 1 comment 0 reactions 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.