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

Kotlinx序列化与Atlas SDK结合:反序列化能否忽略type的setter?

问题

我正尝试将kotlinx.serialization与Atlas Device SDK结合使用,计划通过Kotlin序列化type字段,借助Atlas SDK将_type字段存入数据库。因此在type的setter方法中会同步为_type赋值,但测试序列化时发现_type未被正确设置,请问反序列化过程中能否忽略type的setter?

测试代码

@Test
fun testClassTest() {
    val dialogValue = TestClass(type = HeaderDialogValueType.DECIMAL_NUMBER)
    val dialogValueString = KotlinUtils.json.encodeToString(dialogValue)
    println(dialogValueString)
    val dialogValue2 = KotlinUtils.json.decodeFromString<HeaderDialogValue>(dialogValueString)

    assert(dialogValue.type == dialogValue2.type)
}

待序列化并通过Atlas SDK存储的类

@Serializable
class TestClass() {
    @Transient
    private var _type: String = HeaderDialogValueType.TEXT.name

    var type: HeaderDialogValueType = HeaderDialogValueType.TEXT
        get() {
            return HeaderDialogValueType.valueOf(_type)
        }
        set(value) {
            field = value
            _type = value.name
        }

    constructor(type: HeaderDialogValueType) : this() {
        this.type = type
    }
}

枚举类

@Serializable
enum class HeaderDialogValueType {
    @SerialName("NUMBER")
    NUMBER,
    @SerialName("TEXT")
    TEXT,
    @SerialName("ROLL")
    ROLL,
    @SerialName("DECIMAL_NUMBER")
    DECIMAL_NUMBER
}
解决方案

可以通过以下几种方式实现反序列化时忽略type的setter,同时保证_type字段能正确同步:

  • 给setter添加@set:Transient注解
    直接在type的setter上标记@set:Transient,让kotlinx.serialization反序列化时绕过自定义setter,直接给幕后字段赋值。之后通过@AfterDeserialize注解的方法手动同步_type的值:

    @Serializable
    class TestClass() {
        @Transient
        private var _type: String = HeaderDialogValueType.TEXT.name
    
        var type: HeaderDialogValueType = HeaderDialogValueType.TEXT
            get() {
                return HeaderDialogValueType.valueOf(_type)
            }
            @set:Transient
            set(value) {
                field = value
                _type = value.name
            }
    
        constructor(type: HeaderDialogValueType) : this() {
            this.type = type
        }
    
        @AfterDeserialize
        private fun afterDeserialize() {
            _type = type.name
        }
    }
    
  • 重构逻辑让_type成为唯一数据源
    既然type的getter是从_type取值,直接把type改成无幕后字段的属性,同时给_type绑定序列化逻辑(映射到JSON的type字段):

    @Serializable
    class TestClass() {
        private var _type: String = HeaderDialogValueType.TEXT.name
    
        var type: HeaderDialogValueType
            get() = HeaderDialogValueType.valueOf(_type)
            set(value) {
                _type = value.name
            }
    
        constructor(type: HeaderDialogValueType) : this() {
            this.type = type
        }
    
        @Serializer(forClass = TestClass::class)
        companion object : KSerializer<TestClass> {
            override val descriptor: SerialDescriptor = buildClassSerialDescriptor("TestClass") {
                element("type", HeaderDialogValueType.serializer().descriptor)
            }
    
            override fun serialize(encoder: Encoder, value: TestClass) {
                encoder.encodeSerializableElement(descriptor, 0, HeaderDialogValueType.serializer(), value.type)
            }
    
            override fun deserialize(decoder: Decoder): TestClass {
                val type = decoder.decodeSerializableElement(descriptor, 0, HeaderDialogValueType.serializer())
                return TestClass(type)
            }
        }
    }
    

    这种方式反序列化时直接通过构造函数初始化type,自然会同步_type,逻辑更简洁。

  • 拆分字段+反序列化后同步
    把kotlinx.serialization实际序列化的字段和业务字段拆分,反序列化完成后再同步_type:

    @OptIn(ExperimentalSerializationApi::class)
    @Serializable
    class TestClass() {
        @Transient
        private var _type: String = HeaderDialogValueType.TEXT.name
    
        private var _serializedType: HeaderDialogValueType = HeaderDialogValueType.TEXT
    
        var type: HeaderDialogValueType
            get() = HeaderDialogValueType.valueOf(_type)
            set(value) {
                _serializedType = value
                _type = value.name
            }
    
        constructor(type: HeaderDialogValueType) : this() {
            this.type = type
        }
    
        @AfterDeserialize
        private fun afterDeserialize() {
            _type = _serializedType.name
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:20:16