Kotlin多平台开启ProGuard后序列化报错:找不到类序列化器
问题:开启代码混淆后Kotlinx序列化报错
现象
构建应用时,设置isMinifyEnabled = false可正常运行;启用该选项后,出现序列化相关报错。
报错堆栈
ea.j: Serializer for class 'b' is not found. Mark the class as @Serializable or provide the serializer explicitly. at ia.d1.d(Unknown Source:33) at ia.c1.l(Unknown Source:5) at ea.m.d(Unknown Source:22) at ea.l.b(Unknown Source:0) at ua.a$b.l(Unknown Source:79) at ua.a$b.o(Unknown Source:8) at ua.a$b.Z(Unknown Source:4) at e8.a.b(Unknown Source:249) at e8.a$a.l(Unknown Source:10) ...
序列化类定义
@Serializable data class LoginResponse(val accessTokens: ServerTokens, val magisterTokens: TokenResponse, val tenantUrl: String, @Required val type: Int = 1) // Types: 1 = completion
相关业务代码
client.webSocket(host = SERVER_URL, port = 8080, path = EXCHANGE_URL.encodedPath) { send(Json.encodeToString(loginRequest)) incoming.consumeEach { frame -> println("Received frame: $frame") if (frame is Frame.Text) { val json = Json.parseToJsonElement(frame.readText()).jsonObject if (json["type"].toString().toInt() == 1) { response = Json.decodeFromString<LoginResponse>(frame.readText()) // <--- 推测此处为问题代码 } } else if (frame is Frame.Close) { if (frame.readReason()?.knownReason != CloseReason.Codes.NORMAL) { println("Error: ${frame.readReason()?.message}") throw Exception("Received: ${frame.readReason()?.message}") } } } }
已尝试无效方案
- 应用Kotlinx序列化官方Android混淆规则
- 清理并重建项目
- 添加自定义混淆规则
项目环境
- Kotlin 1.7.10
- Kotlin Multiplatform
- KotlinX Serialization Json 1.4.0
- Ktor 2.0.3
- 注:
@Serializable类位于多平台项目的shared模块,序列化操作在androidApp模块中执行
解决方案
1. 配置shared模块的混淆规则
KMM项目中,shared模块需单独配置混淆规则,不能仅在androidApp模块设置:
- 在
shared模块的build.gradle.kts中启用混淆:
android { buildTypes { release { minifyEnabled true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } }
- 在
shared模块的proguard-rules.pro中添加序列化保护规则:
# Kotlinx Serialization 基础保护规则 -keepattributes *Annotation*, InnerClasses -dontnote kotlinx.serialization.SerializationKt -keep,includedescriptorclasses class **$$serializer { *; } -keepclassmembers class ** { *** Companion; } -keepclasseswithmembers class ** { kotlinx.serialization.KSerializer serializer(...); } # 保留项目中所有序列化类及嵌套类 -keep @kotlinx.serialization.Serializable class ** { *; } -keep class com.yourpackage.LoginResponse, com.yourpackage.ServerTokens, com.yourpackage.TokenResponse { *; }
替换com.yourpackage为项目实际包名。
2. 显式指定序列化器
在反序列化时直接传入类的序列化器,避免混淆后反射找不到类:
// 替换原有反序列化代码 response = Json.decodeFromString(LoginResponse.serializer(), frame.readText())
3. 升级依赖版本
Kotlin 1.7.10推荐搭配Kotlinx Serialization 1.4.1,当前1.4.0可能存在兼容性问题,升级依赖:
在shared模块的build.gradle.kts中修改:
plugins { kotlin("multiplatform") kotlin("plugin.serialization") version "1.7.10" } dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") }
4. 临时禁用R8全模式
若以上方法均无效,可临时关闭R8全模式(不建议长期使用),在项目根目录的gradle.properties中添加:
android.enableR8.fullMode=false
内容的提问来源于stack exchange,提问作者Demipho
相关产品推荐
相关产品推荐

