Ktor:如何序列化/反序列化 JSON-API (vnd.api+json)

Posted

技术标签:

【中文标题】Ktor:如何序列化/反序列化 JSON-API (vnd.api+json)【英文标题】:Ktor: How to serialize/deserialise JSON-API (vnd.api+json) 【发布时间】:2021-01-22 14:04:16 【问题描述】:

我希望使用 Ktor 在 Kotlin 中重写 Spring javafx 应用程序。我是 Spring 和 Ktor 的新手。

我无法使用 Ktor 弄清楚如何处理 POJO 的序列化和反序列化。 (这些 POJO 是公共库的一部分)。

我尝试通过 Ktor 向其提供请求的 API 使用:

将 ORM 休眠为 ORM 映射器 使用 RSQL 过滤器省略以服务 JSON-API conform data

例如“数据/事件”将返回:


  "data": [
    
      "type": "event",
      "id": "15b6c19a-6084-4e82-ada9-6c30e282191f",
      "attributes": 
        "imageUrl": null,
        "name": "some text",
        "type": "NUMERIC"
      
    , // and more event objects
  ]

查看 spring 应用程序中的代码库,看起来他们正在使用 RestTemplate 将上述内容反序列化为 Event 类(它只有一个 id、imageUrl、name 和 type 作为变量)。 Spring 似乎自动知道如何从 JSON-API 获取 POJO。

我怎样才能对 Ktor 做同样的事情?我尝试了最简单的:

val response = client.request<List<Event>>("data/event")

使用序列化器作为 gson:

    install(JsonFeature) 
        serializer = GsonSerializer()
    

但这会导致一个 Event 对象列表,其中没有正确设置它们的变量。

我必须做一个包装类:

data class MyWrapper(val data: List<Event>)

然后它将使用正确设置的对象id 填充列表,但没有其他属性。所以默认情况下,看起来 Ktor 没有为 JSON-API 配置。我该如何更改?

【问题讨论】:

【参考方案1】:

我相信 JSON:API 不支持开箱即用。您需要编写自己的序列化程序,或者使用另一个包装类:

class JSONAPI<T>(val type: String, val id: String, val attributes: T)
data class MyWrapper(val data: List<JSONAPI<Event>>)

这里的问题是Event 中除id 之外的所有字段都将被填充。所以你需要调整反序列化结果:

 val response: List<Event> = client.request<MyWrapper>("data/event").data.filterNotNull().map  it.attributes.copy(id = it.id) 

【讨论】:

以上是关于Ktor:如何序列化/反序列化 JSON-API (vnd.api+json)的主要内容,如果未能解决你的问题,请参考以下文章

Ktor Websocket 功能与 ktor 中的 ContentNeogation 功能 (JSON / GSON)

“未找到转换:类 io.ktor.utils.io.ByteChannelNative”错误使用 Ktor

如何使用 kotlinx.serialization 在 Ktor 中序列化 Web Socket Frame.text

如何使用 ktor 解析 HTTP 标头

是否可以使用 Ktor 和/或 Kotlin 多平台在 Rest API 和 Android 应用程序之间“共享”公开的数​​据?

在 Ktor 中指定要序列化为 JSON 的类字段