Skip to content

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

@nise-nabe

Description

@nise-nabe

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions