Jetpack Compose中用kotlinx.serialization序列化含SnapshotStateList的类失败怎么办
解决SnapshotStateList序列化异常方案
问题原因
kotlinx.serialization默认未提供SnapshotStateList的内置序列化器,即使该类是List的子类,序列化框架也不会自动匹配普通List的序列化器,因此会抛出找不到序列化器的错误。
方案1:单属性指定序列化器(无需全局配置)
直接给SnapshotStateList类型的属性加@Serializable注解,指定使用ListSerializer作为序列化器即可,示例代码如下:
import kotlinx.serialization.Serializable import kotlinx.serialization.builtins.ListSerializer @Serializable data class ListContainer( // 若列表存储自定义类型,将String::class.serializer()替换为对应类型的序列化器 @Serializable(with = ListSerializer::class) val dataList: SnapshotStateList<String> )
方案2:全局注册序列化器(无需逐个属性加注解)
如果项目中多处使用SnapshotStateList作为属性类型,可以统一注册序列化规则,避免重复加注解:
- 构建序列化模块,绑定
SnapshotStateList与对应序列化规则
import kotlinx.serialization.modules.SerializersModule import androidx.compose.runtime.snapshots.SnapshotStateList import kotlinx.serialization.builtins.ListSerializer val composeSerializersModule = SerializersModule { contextual(SnapshotStateList::class) { typeArgs -> ListSerializer(typeArgs[0]) } }
- 初始化Json序列化工具时传入该模块
import kotlinx.serialization.json.Json val json = Json { serializersModule = composeSerializersModule }
完成配置后,实体类无需额外添加属性级注解即可正常序列化:
@Serializable data class ListContainer( val dataList: SnapshotStateList<String> )
可选优化:反序列化直接生成SnapshotStateList
上述两种方案默认反序列化后得到普通ArrayList,如果需要反序列化后直接拿到SnapshotStateList,可以自定义专用序列化器:
import kotlinx.serialization.KSerializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.builtins.ListSerializer import androidx.compose.runtime.toMutableStateList class SnapshotStateListSerializer<T>( elementSerializer: KSerializer<T> ) : KSerializer<SnapshotStateList<T>> { private val delegate = ListSerializer(elementSerializer) override val descriptor: SerialDescriptor = delegate.descriptor override fun serialize(encoder: Encoder, value: SnapshotStateList<T>) { delegate.serialize(encoder, value) } override fun deserialize(decoder: Decoder): SnapshotStateList<T> { return delegate.deserialize(decoder).toMutableStateList() } }
使用时替换之前的ListSerializer即可,也可以直接注册到全局序列化模块中。
内容的提问来源于stack exchange,提问作者Waqas Tahir
相关产品推荐
相关产品推荐

