未找到“响应”类的 Ktor 序列化程序

Posted

技术标签:

【中文标题】未找到“响应”类的 Ktor 序列化程序【英文标题】:Ktor Serializer for class 'Response' is not found 【发布时间】:2022-01-09 10:19:21 【问题描述】:

插件和依赖:

id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
implementation "io.ktor:ktor-serialization:$ktor_version"

Application文件:

fun main() 
    embeddedServer(Netty, port = 8080, host = "0.0.0.0") 
        install(ContentNegotiation) 
            json()
        

        userRouter()
    .start(wait = true)

UserRouter:

fun Application.userRouter() 
    routing 
        get("/users/id") 
            val id = call.parameters["id"]?.toInt() ?: -1
            val user = User("Sam", "sam@gmail.com", "abc123")

            val response = if (id == 1) 
                Response("hahaha", false)
             else 
                Response(user, true)        //< - here, use String type will work
            

            call.respond(response)
        
    

User:

@Serializable
data class User(
    val name: String,
    val email: String,
    val password: String
)

Response:

@Serializable
data class Response<T>(
    val data: T,
    val success: Boolean
)

日志:

2021-12-02 18:04:34.214 [eventLoopGroupProxy-4-1] ERROR ktor.application - Unhandled: GET - /users/7
kotlinx.serialization.SerializationException: Serializer for class 'Response' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
    at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
    at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:155)

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

问题是response 变量的类型是Response&lt;out Any&gt;StringUser 类型之间的最小公分母是Any)并且序列化框架无法序列化Any 类型。

【讨论】:

奇怪的是,它在本教程中有效:youtu.be/uhNF4wK4hWU。 @SamChen,教程不同,它使用两个单独的响应调用(具有不同的参数类型)。此处的响应被具体化,因此它实际上捕获了静态类型,在问题案例中,静态类型是两个响应之间的共同点。在没有鉴别器的情况下返回变量类型存在不同的问题,但这是一个不同的讨论。【参考方案2】:

这很奇怪,以下工作,但对我来说它们是一样的:

get("/users/id") 
    val id = call.parameters["id"]?.toInt() ?: -1
    val user = User("Sam", "sam@gmail.com", "abc123")

   /* val response = if (id == 1)       //<- determine response here won't work, why?
        Response("hahaha", false)
     else 
        Response(user, true)
    

    call.respond(response)*/

    if (id == 1) 
        call.respond(Response("hahaha", false))
     else 
        call.respond(Response(user, true))
    

【讨论】:

他们不一样。在这种情况下,第一个respond 接收Response&lt;String&gt; 类型的值,第二个响应接收Response&lt;User&gt; 类型的值。原始案例使用单个变量来保存两者,因此类型为Response&lt;Any&gt;。请注意,kotlinx.serialization 是一个静态框架,使用静态类型,而不是运行时类型。 @Paul de Vrieze 有帮助,谢谢。【参考方案3】:

当你将一个可以为空的泛型设置为空时,你应该给一个泛型一个类型,否则,插件不知道如何序列化它。 例如。

//define
@Serializable
data class Response<T>(
    val data: T?,
    val success: Boolean
)

///usage:
val response = Response<String>(null, false)

【讨论】:

以上是关于未找到“响应”类的 Ktor 序列化程序的主要内容,如果未能解决你的问题,请参考以下文章

Ktor 客户端的 JsonFeature 未解决

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

数据类中的默认参数未使用 ktor 序列化程序转换为 json

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

Ktor WebSockets:kotlinx.serialization.SerializationException:找不到类“DefaultClientWebSocketSession”的序列化

为啥 ktor 序列化不支持序列化不同元素类型的集合?