自定义序列化器
处理特殊类型
自定义序列化器 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
为什么需要自定义序列化器
有些类型没有内置序列化器,例如 java.util.Date、LocalDate、UUID,以及第三方库中的类型。
自定义序列化器定义了这类类型如何映射为序列化形式,以及如何从序列化形式还原。
KSerializer 接口
自定义序列化器通过实现 KSerializer<T>,提供三个成员:descriptor、serialize 和 deserialize。
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder为 LocalDate 编写序列化器
将 LocalDate 映射为 ISO 字符串,并支持从 ISO 字符串还原。描述符将其声明为原始字符串。
import java.time.LocalDate
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
object LocalDateSerializer : KSerializer<LocalDate> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDate) =
encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): LocalDate =
LocalDate.parse(decoder.decodeString())
}使用 @Serializable(with = ...)
使用 @Serializable(with = ...) 将序列化器应用于特定属性。
import java.time.LocalDate
import kotlinx.serialization.Serializable
@Serializable
data class Event(
val name: String,
@Serializable(with = LocalDateSerializer::class)
val date: LocalDate
)文件级 @UseSerializers
为了避免标注每个属性,可以使用 @file:UseSerializers 在每个文件中声明一次序列化器。
@file:UseSerializers(LocalDateSerializer::class)
import kotlinx.serialization.UseSerializers
import java.time.LocalDate
import kotlinx.serialization.Serializable
@Serializable
data class Event(val name: String, val date: LocalDate)上下文序列化
在 Json { } 模块中全局注册序列化器,并使用 @Contextual 标记属性。运行时会从模块中解析序列化器。
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import java.time.LocalDate
@Serializable
data class Event(val name: String, @Contextual val date: LocalDate)注册 SerializersModule
构建一个将类型绑定到其序列化器的模块,然后将其传递给 Json。
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import java.time.LocalDate
val module = SerializersModule {
contextual(LocalDate::class, LocalDateSerializer)
}
val json = Json { serializersModule = module }复合序列化器
对于包含多个字段的类型,请使用 encodeStructure / decodeStructure 和结构化描述符,而不是原始描述符。
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
val descriptor = buildClassSerialDescriptor("Color") {
element<Int>("r")
element<Int>("g")
element<Int>("b")
}替身模式
一种更简单的替代方案是:序列化一个编译器已经支持的私有替身数据类,然后在它与真实类型之间进行映射。与手动编写编码和解码相比,所需样板代码更少。
import kotlinx.serialization.Serializable
@Serializable
private data class ColorSurrogate(val r: Int, val g: Int, val b: Int)选择实现方式
请选择最适合需求的轻量方案:
- @Serializable(with=) — 用于单个属性
- @UseSerializers — 用于整个文件
- @Contextual + 模块 — 用于整个应用,在运行时解析
- 替身 — 用于以最少代码处理复合类型
原始描述符与结构化描述符
描述符必须与编码方式匹配:
- 单个值(字符串/整数)→
PrimitiveSerialDescriptor - 多个字段 →
buildClassSerialDescriptor
两者不匹配会导致运行时序列化错误。
快速检查
您想将单个 LocalDate 序列化为一个 ISO 字符串。哪种描述符合适?
回顾
自定义序列化器可以处理插件不了解的类型:
- 实现带有 descriptor、serialize 和 deserialize 的
KSerializer<T> - 通过
@Serializable(with=)、@UseSerializers或@Contextual+ 模块应用 - 使描述符的种类与编码方式匹配
Serialization 课程到此结束。
常见问题解答
「自定义序列化器」课时是免费的吗?
是的 — 「自定义序列化器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「自定义序列化器」这节课中我会学到什么?
处理特殊类型 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「自定义序列化器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。