如何解决为什么在ktor-serialization中不支持序列化不同元素类型的集合?
我正在尝试制作一个简单的服务器,该服务器以JSON提供序列化列表。 the official blog post的多态序列化部分中的示例就是要序列化的列表。
但是使用ktor的序列化功能,我得到了以下异常。
21:53:25.536 [nioEventLoopGroup-4-1] ERROR ktor.application - Unhandled: GET - /
java.lang.IllegalStateException: Serializing collections of different element types is not yet supported. Selected serializers: [DirectMessage,BroadcastMessage]
at io.ktor.serialization.SerializerLookupKt.elementSerializer(SerializerLookup.kt:71)
由于密封类是选择Kotlin的关键功能,所以我真的很奇怪为什么不支持此功能。
ktor串行化是否有充分的理由不支持这一点?还是应该发布从SerializerLookup.kt删除此支票的问题?
我通过选择IntelliJ中的New Project> Kotlin> Application来编写此代码。修改后的代码如下所示。
我的服务器.kt:
import io.ktor.application.*
import io.ktor.features.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.serialization.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import kotlinx.serialization.Serializable
@Serializable
sealed class Message {
abstract val content: String
}
@Serializable
data class BroadcastMessage(override val content: String) : Message()
@Serializable
data class DirectMessage(override val content: String,val recipient: String) : Message()
val data: List<Message> = listOf(
DirectMessage("Hey,Joe!","Joe"),BroadcastMessage("Hey,all!")
)
fun main() {
embeddedServer(Netty,port = 8080,host = "127.0.0.1") {
install(ContentNegotiation) {
json()
}
routing {
get("/") {
call.respond(data)
}
}
}.start(wait = true)
}
我的build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.4.10"
application
kotlin("plugin.serialization") version "1.4.10"
}
group = "com.example.ktor.serialization"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
jcenter()
maven {
url = uri("https://dl.bintray.com/kotlin/ktor")
}
maven {
url = uri("https://dl.bintray.com/kotlin/kotlinx")
}
}
dependencies {
testImplementation(kotlin("test-junit5"))
implementation("io.ktor:ktor-server-netty:1.4.1")
implementation("io.ktor:ktor-html-builder:1.4.1")
implementation("io.ktor:ktor-serialization:1.4.1")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")
implementation("ch.qos.logback:logback-classic:1.2.3")
}
tasks.withType<KotlinCompile>() {
kotlinOptions.jvmTarget = "11"
}
application {
mainClassName = "ServerKt"
}
解决方法
如stacktrace this is not supported yet.
中所述,所以可能有一天会出现。
但是,在这种情况下仍可以解决。 问题出在Ktor,而不是Kotlinx序列化。 因此,您可以将数据序列化为JSON,然后将其作为响应发送,例如:
fun Application.module(testing: Boolean = false) {
install(ContentNegotiation) { json() }
routing {
get("/") {
val data: List<Message> = listOf(
DirectMessage("Hey,Joe!","Joe"),BroadcastMessage("Hey,all!")
)
val string = Json.encodeToString(data)
call.respondText(string,contentType = ContentType.Application.Json)
}
}
}
@Serializable
sealed class Message {
abstract val content: String
}
@Serializable
data class BroadcastMessage(override val content: String) : Message()
@Serializable
data class DirectMessage(override val content: String,val recipient: String) : Message()
,
原因是我们没有特定的类型信息,只能在运行时分析实例类。分析和运行时类型交集不是一件容易的事,并且肯定会非常低效,这在服务器端是不可接受的。
使用typeOf
可能会有所帮助,但我们尚未分析这种更改对性能的影响(包括分配配置文件)。另一个原因是我们不了解typeOf
(它不存在),并且call.respond
的设计没有它,所以这种变化肯定会是一个重大变化。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。