Spring Boot中Kotlin DTO作为@RequestBody触发400 Bad Request问题
在混合Java与Kotlin的Spring Boot项目中,已引入并配置jackson-kotlin模块:
<dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-kotlin</artifactId> <version>2.18.1</version> </dependency>
配置类如下:
@Configuration open class JacksonConfig { @Bean open fun objectMapper(): ObjectMapper { return ObjectMapper().registerKotlinModule() } }
调用以下接口时:
@PostMapping("/test") fun test(@RequestBody promptRequest: PromptRequest): ResponseEntity<String> { return ResponseEntity(promptRequest.prompt, HttpStatus.OK) }
当PromptRequest为Kotlin数据类时:
data class PromptRequest (val prompt: String)
请求始终返回HTTP 400 Bad Request:
HTTP/1.1 400 Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/problem+json Transfer-Encoding: chunked Date: Tue, 12 Nov 2024 09:00:56 GMT Connection: close { "type": "about:blank", "title": "Bad Request", "status": 400, "detail": "Failed to read request", "instance": "/test", "properties": null }
改为Java类则正常返回200:
public class PromptRequest { public String prompt; }
HTTP/1.1 200 Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: text/plain;charset=UTF-8 Content-Length: 42 Date: Tue, 12 Nov 2024 09:05:08 GMT input prompt Response code: 200; Time: 3171ms (3 s 171 ms); Content length: 12 bytes (12 B)
已配置jackson-kotlin模块但问题依旧,服务器日志无报错,求原因及解决办法。
问题出在自定义ObjectMapper的方式错误:直接new ObjectMapper()会完全替换Spring Boot默认配置好的ObjectMapper实例,丢失了Spring Boot自动配置中针对JSON序列化/反序列化的关键设置(比如消息转换器集成、属性命名策略、默认模块注册等)。虽然手动注册了Kotlin模块,但缺少其他必要配置,导致Kotlin数据类的反序列化失败。
另外,Kotlin数据类默认只有带参数的构造函数,Jackson Kotlin模块需要依赖这个构造函数进行反序列化,但如果ObjectMapper没有正确集成Spring上下文,可能无法正确识别构造函数参数。
推荐以下几种正确配置方式:
方式1:使用Jackson2ObjectMapperBuilder构建(保留默认配置)
通过Spring提供的Jackson2ObjectMapperBuilder构建ObjectMapper,会保留所有Spring Boot默认配置,同时添加Kotlin模块:
@Configuration open class JacksonConfig { @Bean open fun objectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper { return builder .modulesToInstall(KotlinModule::class.java) .build() } }
方式2:通过WebMvcConfigurer添加模块
不需要自定义ObjectMapper,直接配置消息转换器并注册Kotlin模块:
@Configuration open class WebConfig : WebMvcConfigurer { override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) { val converter = MappingJackson2HttpMessageConverter() converter.objectMapper.registerModule(KotlinModule()) converters.add(0, converter) } }
方式3:删除自定义配置(最推荐)
在Spring Boot项目中,只要引入jackson-module-kotlin依赖,Spring Boot会自动将Kotlin模块注册到默认的ObjectMapper中。直接删除自定义的JacksonConfig类,重启项目即可解决问题。
- 删除自定义的
JacksonConfig配置类 - 确保
jackson-module-kotlin依赖存在 - 重启项目,用Kotlin数据类测试接口,请求体使用标准JSON格式(如
{"prompt": "input prompt"}),并设置请求头Content-Type: application/json
内容的提问来源于stack exchange,提问作者janssen-dev

