Kotlinx.serialization 格式详解:CBOR与ProtoBuf实战指南
前言
Kotlinx.serialization 是 Kotlin 官方的序列化框架,除了常见的 JSON 格式外,还支持多种二进制格式。本文将深入探讨其中的 CBOR 和 Protocol Buffers (ProtoBuf) 两种二进制格式,帮助开发者理解它们的特性和使用场景。
CBOR 格式详解
什么是 CBOR
CBOR (Concise Binary Object Representation) 是一种紧凑的二进制 JSON 编码格式,由 RFC 7049 定义。它与 JSON 功能相似但采用二进制表示,体积更小,适合网络传输和 IoT 设备通信。
基本使用
@Serializable
data class Project(val name: String, val language: String)
fun main() {
val data = Project("kotlinx.serialization", "Kotlin")
// 编码为字节数组
val bytes = Cbor.encodeToByteArray(data)
// 解码回对象
val obj = Cbor.decodeFromByteArray<Project>(bytes)
}
核心特性
-
忽略未知键:在 IoT 场景中,设备 API 可能不断演进添加新字段。通过配置
ignoreUnknownKeys = true
可以兼容旧版本代码。 -
字节数组处理:
- 默认使用 major type 4 (数组)编码
- 使用
@ByteString
注解可强制使用 major type 2 (字节串) - 全局配置
alwaysUseByteString
可统一处理方式
-
长度编码方式:
- 不定长编码 (默认):使用终止符标记结束
- 定长编码 (
useDefiniteLengthEncoding=true
):前置元素数量
-
标签系统:
@KeyTags
/@ValueTags
:为键值添加元数据标签@ObjectTags
:强制类实例始终带标签- 验证开关:
verifyKeyTags
/verifyValueTags
/verifyObjectTags
-
数组优化:
- 使用
@CborArray
注解可将类序列化为 CBOR 数组而非映射,减少体积
- 使用
Protocol Buffers 格式详解
什么是 ProtoBuf
Protocol Buffers 是 Google 开发的二进制序列化格式,特点是体积小、速度快,常用于高性能通信场景。与 CBOR 不同,ProtoBuf 通常需要预定义 schema。
基本使用
@Serializable
data class Project(val name: String, val language: String)
fun main() {
val data = Project("kotlinx.serialization", "Kotlin")
val bytes = ProtoBuf.encodeToByteArray(data)
val obj = ProtoBuf.decodeFromByteArray<Project>(bytes)
}
核心特性
-
字段编号:
- 默认自动分配编号,不利于版本兼容
- 使用
@ProtoNumber
显式指定稳定编号
@Serializable data class Project( @ProtoNumber(1) val name: String, @ProtoNumber(3) val language: String )
-
整数编码:
DEFAULT
:变长编码,适合小非负数SIGNED
:ZigZag 编码,适合小有符号数FIXED
:固定长度编码
@Serializable class Data( @ProtoType(ProtoIntegerType.DEFAULT) val a: Int, // 变长 @ProtoType(ProtoIntegerType.SIGNED) val b: Int, // ZigZag @ProtoType(ProtoIntegerType.FIXED) val c: Int // 固定 )
-
列表处理:
- 默认作为重复字段处理
- 支持打包字段优化 (
packed=true
)
-
Oneof 字段:
- 实验性功能,模拟 proto3 的 oneof 特性
- 可用于实现互斥字段
格式选择建议
-
CBOR 适用场景:
- 需要与 JSON 兼容但更小的体积
- IoT 设备通信
- 需要动态 schema 的场景
-
ProtoBuf 适用场景:
- 高性能 RPC 通信
- 需要严格版本控制的 API
- 已知数据结构的长期存储
性能优化技巧
-
CBOR:
- 对频繁传输的
ByteArray
使用@ByteString
- 考虑启用
useDefiniteLengthEncoding
减少解析开销 - 合理使用标签系统减少元数据传输
- 对频繁传输的
-
ProtoBuf:
- 为所有字段显式指定
@ProtoNumber
- 根据数值范围选择合适的整数编码
- 对数值列表使用打包字段
- 为所有字段显式指定
总结
Kotlinx.serialization 的 CBOR 和 ProtoBuf 支持为 Kotlin 开发者提供了高效的二进制序列化方案。CBOR 更适合需要 JSON 兼容性和灵活性的场景,而 ProtoBuf 则擅长高性能和强类型通信。理解它们的特性和配置选项,可以帮助开发者根据具体需求选择最合适的序列化方案。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考