如何声明接收嵌套列表查询参数的Controller方法及调用?
关于GET请求接收List<List>查询参数的解决方案
首先直接给出结论:你当前的写法默认不可行,因为Spring MVC的默认查询参数解析器无法自动将URL中的JSON格式字符串转换为List<List<String>>类型。不过可以通过自定义参数解析逻辑或者调整参数传递格式来实现,完全满足GET请求的幂等性和可缓存需求。
问题原因
Spring默认处理查询参数时,对于List类型的参数,只会解析两种格式:
- 重复参数名:比如
options=aaa&options=bbb,会解析为List<String> - 逗号分割字符串:比如
options=aaa,bbb,需开启@RequestParam的split属性或全局配置
但你传入的是JSON格式的嵌套列表字符串,Spring没有内置的解析逻辑处理这种情况,因此会抛出类型转换异常。
解决方案一:自定义JSON参数解析器
通过实现Converter<String, List<List<String>>>,让Spring能够将JSON字符串转换为目标类型:
1. 编写自定义Converter
import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.core.convert.converter.Converter import org.springframework.stereotype.Component @Component class NestedListConverter(private val objectMapper: ObjectMapper) : Converter<String, List<List<String>>> { override fun convert(source: String): List<List<String>> { return objectMapper.readValue(source, object : com.fasterxml.jackson.core.type.TypeReference<List<List<String>>>() {}) } }
2. 保留原有Controller写法
你的Controller方法无需改动,Spring会自动使用这个Converter来解析options参数:
import org.springframework.http.ResponseEntity import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @Validated class SearchController { suspend fun v1GetSearch( @PathVariable("id") id: String, @Valid @RequestParam(value = "options", required = false) options: List<List<String>>? ): ResponseEntity<SearchResponse> { // 业务逻辑实现 return ResponseEntity.ok(SearchResponse()) } }
3. 注意事项
- 确保URL中的JSON字符串已正确编码(方括号、引号等特殊字符需转义),实际请求URL示例:
http://localhost:8080/search/id?options=%5B%5B%22aaa%22%2C%22bbb%22%2C%22ccc%22%2C%22ddd%22%5D%2C%5B%22abcd%22%2C%22abcd%22%2C%22abcd%22%2C%22abcd%22%5D%5D
- Spring Boot环境下,Jackson的
ObjectMapper会自动注入,无需额外配置。
解决方案二:使用扁平式参数传递
如果不想用JSON格式,可以采用更符合HTTP查询参数规范的扁平传递方式,Spring默认支持这种嵌套列表的解析:
1. 参数传递格式
有两种常用的扁平传递方式:
- 索引式:
http://localhost:8080/search/id?options[0]=aaa&options[0]=bbb&options[0]=ccc&options[0]=ddd&options[1]=abcd&options[1]=abcd&options[1]=abcd&options[1]=abcd
- 重复参数名+逗号分割子列表:
http://localhost:8080/search/id?options=aaa,bbb,ccc,ddd&options=abcd,abcd,abcd,abcd
使用第二种方式时,需要在application.yml中开启逗号分割列表的解析配置:
spring: mvc: format: query: comma-separated-lists: true
2. Controller方法写法
保持你原有的写法即可,Spring会自动将上述格式的参数解析为List<List<String>>。
总结
两种方案都能实现GET请求接收嵌套列表参数,满足幂等性和可缓存的需求:
- 方案一更适合前端需要传递复杂嵌套结构的场景,但要注意URL编码问题
- 方案二更符合HTTP查询参数的传统规范,避免JSON编码的麻烦
内容的提问来源于stack exchange,提问作者Haf
相关产品推荐
相关产品推荐

