ktor - Ktor Location API:将 JSON 映射到通用 Map 对象
问题描述
当我将常规路由 API 与 GSON 一起使用时,我可以使用以下代码片段将 JSON 参数反序列化为 Map<String, Any>:
post("/books") {
val request = call.receive<Map<String, Any>>()
...
}
在我的例子中,请求是 com.google.gson.internal.LinkedTreeMap 的一个实例。
有没有办法使用 Location API 来做同样的事情?当我用具体成员定义数据类但我找不到使用地图的方法时,它工作正常。我正在尝试以下几件事:
@Location ("/books")
<some magic class definition>
fun Application.bookModule() {
routing {
post<BookRequest> {
val request = call.receive<BookRequest>()
...
}
但我还没有想出任何可行的方法。帮助?
解决方案
位置仅代表端点的路径和查询参数,因此无法根据请求正文进行路由。位置类的属性应该映射到路径段,例如
@Location ("/books/{title}/{author}") data class BookRequest(
val title: String,
val author: String,
)
要接收请求正文并将其转换为对象,只需使用ContentNegotiation 插件。以下是对curl -v --header "Content-Type: application/json" --request POST --data '{"title":"Hitchhiker", "author":"DNA", "detail":{"foo": "bar"}}' http://localhost:8080/books
请求响应 200 OK 的服务器示例:
import io.ktor.application.*
import io.ktor.features.*
import io.ktor.gson.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.locations.post
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.routing
import io.ktor.server.engine.*
import io.ktor.server.netty.*
fun main(args: Array<String>) {
embeddedServer(Netty, port = 8080) {
install(ContentNegotiation) {
gson()
}
install(Locations)
bookModule()
}.start()
}
fun Application.bookModule() {
routing {
post<BookRequest> {
val request = call.receive<Map<String, Any>>()
println(request)
call.respond(HttpStatusCode.OK)
}
}
}
@Location ("/books") class BookRequest