You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用kotlinx.serialization序列化继承Java抽象类的Kotlin类

解决kotlinx.serialization继承Java抽象类的序列化问题

核心问题

kotlinx.serialization默认仅处理当前类标记为val/var的属性,不会自动识别并处理Java父类的私有字段。直接在Kotlin子类中重复声明同名属性会导致字节码中出现重复字段,进而引发序列化/反序列化逻辑混乱。

正确实现模式

方案1:自定义序列化器(无需修改Java父类)

通过实现KSerializer手动控制序列化和反序列化流程,直接操作Java父类的私有字段:

首先定义Kotlin子类B(不重复声明s属性):

@Serializable(with = BSerializer::class)
class B(s: String) : A(s)

然后实现自定义序列化器:

object BSerializer : KSerializer<B> {
    override val descriptor: SerialDescriptor =
        buildClassSerialDescriptor("B") {
            element<String>("s")
        }

    override fun serialize(encoder: Encoder, value: B) {
        // 通过反射读取Java父类的私有s字段
        val field = A::class.java.getDeclaredField("s")
        field.isAccessible = true
        val sValue = field.get(value) as String
        encoder.encodeStringElement(descriptor, 0, sValue)
    }

    override fun deserialize(decoder: Decoder): B {
        val sValue = decoder.decodeStringElement(descriptor, 0)
        // 调用子类构造,传入s值初始化父类
        return B(sValue)
    }
}

方案2:给Java父类添加Getter(若可修改Java库)

如果能修改Java抽象类A,添加s的getter方法:

public abstract class A {
    private final String s;

    public A(String s) {
        this.s = s;
    }

    // 添加Getter方法
    public String getS() {
        return s;
    }
}

然后在Kotlin子类中利用Getter实现序列化,同时通过构造参数初始化父类:

@Serializable
class B(s: String) : A(s) {
    // 序列化时读取父类的s值
    @SerialName("s")
    @EncodeDefault
    private val serializedS: String
        get() = super.getS()
}

这种方式无需编写完整自定义序列化器,让框架通过Getter读取父类字段,反序列化时直接通过构造参数完成父类初始化。

方案3:使用@Transient避免重复字段(简化版)

如果不想编写完整序列化器,可在Kotlin子类中声明s为val但标记@Transient,通过计算属性提供序列化所需值:

@Serializable
data class B(@Transient val s: String) : A(s) {
    @SerialName("s")
    private val serializedS: String
        get() = s // 构造时已将s传入父类,此处值与父类s完全一致
}

该方式核心是利用Kotlin构造参数传递初始化父类,同时通过计算属性向序列化框架提供正确的s值,避免字节码中出现重复字段。


内容的提问来源于stack exchange,提问作者Max Rosoff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 06:03:09