【问题标题】:Ktor Location API: mapping JSON to generic Map objectKtor Location API:将 JSON 映射到通用 Map 对象
【发布时间】:2021-09-10 11:21:55
【问题描述】:

当我将常规路由 API 与 GSON 一起使用时,我可以使用以下代码 sn-p 将 JSON 参数反序列化为 Map

        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>()
            ...
        }

但我还没有想出任何可行的方法。帮忙?

【问题讨论】:

  • 我可以将call.receive&lt;Map&lt;String, Any&gt;&gt;() 与标准路由一起使用,并与Locations 插件中的一个一起使用。您能否解释一下您的实际行为是什么?
  • 我的印象是使用@Location 注释的类型必须与用于参数的类型相同。不是这样吗?目前我有
  • @Location ("/books") data class BookRequest(val title: String, val author: String, val detail: Map&lt;String, Any&gt;) fun Application.bookModule() { routing { post&lt;BookRequest&gt; { val request = call.receive&lt;Map&lt;String, Any&gt;&gt;() println(request) call.respond(HttpStatusCode.OK) } } }
  • 当我用curl --header "Content-Type: application/json" \ --request POST \ --data '{"title":"Hitchhiker", "author":"DNA", "detail":{"foo": "bar"}}' \ http://localhost:8080/books 调用它时,这会导致 404。当我在下一条评论中实现 get 请求时,它会起作用。 @AlekseiTirman - 感谢您对此进行调查。
  • fun Application.bookModule() { routing { get&lt;BookRequest&gt; { val books = bookHandler.listBooks() val bookRefs = books.map { BookListItem( it.title, URLBuilder(locations.href(BookSearchRequest(it.isbn))).build() ) } val message = FreeMarkerContent("books/booklist.ftl", mapOf("books" to bookRefs)) call.respond(message) }

标签: ktor


【解决方案1】:

位置仅代表端点的路径和查询参数,因此无法根据请求正文进行路由。位置类的属性应该映射到路径段,例如

@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

【讨论】:

  • 这是有道理的,我现在一切正常。感谢您提供详细的描述。如果我在相应文档中提出包含此信息的拉取请求,您认为这会有用吗?
  • 是的,如果文档不清楚的话。
猜你喜欢
  • 1970-01-01
  • 2019-05-27
  • 2020-03-08
  • 1970-01-01
  • 2012-04-23
  • 2017-05-06
  • 2014-11-07
  • 2017-12-24
  • 1970-01-01
相关资源
最近更新 更多