Kotlin密封接口Bar的子类Foo序列化失败问题求助
Kotlinx序列化密封接口多态序列化异常问题
问题代码
@Serializable data class Foo ( var text: String? ) : Bar @Serializable sealed interface Bar { var id: String? val hash: String get() { return this.toString().md5() } } fun save(): Boolean { return try { this.id = this.hash val tmp = Json.encodeToString(this) //save the number to Kali datastore. Datalayer.save(tmp) true } catch (e: Exception) { false } } var aa = Foo("woo") aa.save()
异常信息
kotlinx.serialization.SerializationException: Class 'Foo' is not registered for polymorphic serialization in the scope of 'Bar'.
Mark the base class as 'sealed' or register the serializer explicitly.
异常触发自val tmp = Json.encodeToString(this)行。
依赖配置:
- 序列化依赖:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0") - Kotlin插件:
kotlin("plugin.serialization") version "1.7.20"
问题原因及解决方案
核心问题1:序列化时未指定基类序列化器
虽然Bar是密封接口,但在save()方法中,this的静态类型为Bar,kotlinx.serialization无法自动推断需要使用基类的多态序列化器,导致无法识别子类Foo。
解决方法:序列化时明确传入Bar.serializer()作为参数:
val tmp = Json.encodeToString(Bar.serializer(), this)
核心问题2:代码结构错误
save()函数被定义在Bar接口外部,无法作为Bar实现类的成员方法调用(除非是扩展函数,但代码中未声明),需将其移至Bar接口内部作为成员函数:
@Serializable sealed interface Bar { // ... 原有属性 ... fun save(): Boolean { return try { this.id = this.hash val tmp = Json.encodeToString(Bar.serializer(), this) Datalayer.save(tmp) true } catch (e: Exception) { false } } }
核心问题3:接口属性未实现
Bar接口定义了var id: String?抽象属性,但Foo类未实现该属性,这会导致编译错误。需修正Foo类:
@Serializable data class Foo( var text: String?, override var id: String? // 实现Bar的id属性 ) : Bar
若希望所有子类共享id的默认值,可在Bar接口中设置默认值:
@Serializable sealed interface Bar { var id: String? = null // ... 其他内容 ... }
完整修正代码
import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @Serializable data class Foo( var text: String?, override var id: String? ) : Bar @Serializable sealed interface Bar { var id: String? val hash: String get() { return this.toString().md5() } fun save(): Boolean { return try { this.id = this.hash val tmp = Json.encodeToString(Bar.serializer(), this) Datalayer.save(tmp) true } catch (e: Exception) { false } } } object Datalayer { fun save(data: String) { // 实现存储逻辑 } } fun main() { val aa = Foo("woo", null) aa.save() }
内容的提问来源于stack exchange,提问作者ukeivo
相关产品推荐
相关产品推荐

