Ktor使用Location特性开发REST API时POST JSON参数为空如何解决
问题根因
你遇到POST请求接收的title字段为空的问题,核心通常是两点:
- 未正确安装配置JSON序列化插件,Ktor无法将请求体的JSON数据反序列化为目标类
- 用于Location路由定义的类,未适配序列化规则,导致反序列化时字段匹配失败
可运行完整示例
1. 所需依赖(Gradle Kotlin DSL配置)
dependencies { implementation("io.ktor:ktor-server-core-jvm:2.3.3") implementation("io.ktor:ktor-server-netty-jvm:2.3.3") // Location特性依赖 implementation("io.ktor:ktor-server-locations-jvm:2.3.3") // JSON序列化依赖 implementation("io.ktor:ktor-server-content-negotiation-jvm:2.3.3") implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:2.3.3") }
2. 完整业务代码
import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.netty.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.locations.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.server.locations.* import kotlinx.serialization.Serializable // 同时用于Location路由和请求体反序列化的类需要加@Serializable注解 @Serializable @Location("/books") data class BookRequest(val title: String = "") // 模拟书籍处理逻辑 object BookHandler { private val books = mutableListOf("The Hobbit", "1984") fun listBooks() = books fun addBook(title: String) { books.add(title) } } fun Application.module() { // 安装Location插件 install(Locations) // 安装JSON序列化插件 install(ContentNegotiation) { json() } routing { get<BookRequest> { // 返回书籍列表JSON call.respond(BookHandler.listBooks()) } post<BookRequest> { // 从请求体反序列化得到BookRequest对象 val requestBody = call.receive<BookRequest>() BookHandler.addBook(requestBody.title) // 重定向到新书籍的资源路径,示例用书籍标题作为路径参数 call.respondRedirect("/books/${requestBody.title}") } // 可选:单本书籍详情路由示例 @Serializable @Location("/books/{title}") data class SingleBookRequest(val title: String) get<SingleBookRequest> { req -> call.respond("Book detail: ${req.title}") } } } fun main() { embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true) }
3. 测试验证
执行你原来的curl命令即可:
curl --header "Content-Type: application/json" \ --request POST \ --data '{"title":"Hitchhiker"}' \ http://localhost:8080/books -v
你会看到返回302重定向响应,Location头为/books/Hitchhiker,再调用GET /books接口即可看到新添加的书籍已经在列表中。
注意事项
- 用于反序列化的data class必须添加kotlinx序列化的
@Serializable注解,否则Ktor无法正常解析JSON - 不要混淆Location的路由参数和请求体参数:如果你的Location类有路径参数(比如
/books/{id}里的id),路径参数会被Location插件自动填充,call.receive得到的是请求体里的字段,两者互不影响。
内容的提问来源于stack exchange,提问作者Jerry Preissler
相关产品推荐
相关产品推荐

