Kotlin全栈教程中Ktor服务器POST请求出现java.lang.VerifyError
我正在跟随Kotlin官方全栈应用教程开发,Ktor服务器处理GET请求可正常返回JSON响应,但发送如下POST请求时返回500错误:
POST http://localhost:9090/shoppingList
Content-Type: application/json{
"desc": "Peppers 🌶",
"priority": 5
}
报错日志如下:
2023-01-10 08:53:06.605 [DefaultDispatcher-worker-1] INFO ktor.application - Responding at http://0.0.0.0:9090 2023-01-10 08:53:12.317 [eventLoopGroupProxy-4-2] ERROR ktor.application - Unhandled: POST - /shoppingList java.lang.VerifyError: class kotlinx.serialization.json.internal.StreamingJsonDecoder overrides final method kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object; at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) at ...
服务器代码(完全复制自教程仓库,仅完成第一部分):
val shoppingList = mutableListOf( ShoppingListItem("Cucumbers 🥒", 1), ShoppingListItem("Tomatoes 🍅", 2), ShoppingListItem("Orange Juice 🍊", 3) ) fun main() { embeddedServer(Netty, 9090) { install(ContentNegotiation) { json() } install(CORS) { allowMethod(HttpMethod.Get) allowMethod(HttpMethod.Post) allowMethod(HttpMethod.Delete) anyHost() } install(Compression) { gzip() } routing { route(ShoppingListItem.path) { get { call.respond(shoppingList) } post { shoppingList += call.receive<ShoppingListItem>() call.respond(HttpStatusCode.OK) } delete("/{id}") { val id = call.parameters["id"]?.toInt() ?: error("Invalid delete request") shoppingList.removeIf { it.id == id } call.respond(HttpStatusCode.OK) } } } routing { get("/hello") { call.respondText("Hello, API!") } } }.start(wait = true) }
问题原因
这个VerifyError是Kotlin序列化库版本冲突导致的:kotlinx-serialization-json和kotlinx-serialization-core的版本不匹配,或者项目引入了不同版本的序列化相关依赖,类加载时出现子类重写父类final方法的冲突。
解决步骤
统一序列化库版本:确保项目中所有
kotlinx-serialization相关依赖使用完全相同的版本。如果用Gradle,建议在根级build.gradle.kts定义统一版本变量:val serializationVersion = "1.5.1" // 替换为与Ktor兼容的版本所有序列化依赖都引用该变量:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")匹配Ktor与序列化版本:Ktor的
ContentNegotiation插件依赖特定版本的序列化库,需保证两者版本兼容。比如Ktor 2.3.x对应序列化库1.5.x版本,可参考官方版本对应关系。清理重建项目:执行Gradle的
clean任务清除旧构建文件,再重新执行build或run任务,确保依赖重新下载并正确构建。排查依赖冲突:用Gradle的
dependencies任务查看依赖树:./gradlew dependencies若发现冲突,使用
exclude排除重复或不兼容的依赖。
内容的提问来源于stack exchange,提问作者bsautner

