Protobuf 数据序列化入门指南
核心概念
Protocol Buffers(简称 Protobuf)是 Google 推出的一种高效的数据结构描述语言,用于定义数据格式并实现跨平台、跨语言的序列化与反序列化。相比传统 XML 或 JSON,它具有更小的体积、更高的解析性能和更强的类型安全性。
优势分析
- 体积更小:生成的二进制数据通常仅为 XML/JSON 的 1/10 到 1/3。
- 速度更快:解析效率提升约 20 至 100 倍,尤其适合高频率通信场景。
- 无歧义:通过明确的数据类型定义避免了字段解释错误。
- 多语言支持:自动生成各语言对应的访问类,便于集成到不同技术栈中。
多语言支持列表
| 语言 | 官方仓库 |
|---|---|
| C++ | src |
| Java | java |
| Python | python |
| Objective-C | objectivec |
| C# | csharp |
| JavaScript | js |
| Ruby | ruby |
| Go | golang/protobuf |
| PHP | php |
| Dart | dart-lang/protobuf |
Android 环境配置
4.1 插件与依赖设置
在项目级 build.gradle 中引入 Protobuf 插件:
plugins {
id 'com.google.protobuf' version '0.8.17'
}
在模块级 build.gradle 中配置源码目录与依赖:
android {
sourceSets {
main {
proto {
srcDir 'src/main/proto' // 可选,默认路径为 src/main/proto
}
}
}
}
dependencies {
implementation "com.google.protobuf:protobuf-javalite:3.18.0"
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.14.0"
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite' // 使用轻量级版本,适用于 Android
}
}
}
}
}
4.2 定义数据模型
创建 src/main/proto/data.proto 文件:
syntax = "proto3";
option java_package = "com.example.data";
option java_multiple_files = true;
message AnimalGroup {
int32 group_id = 1;
repeated Dog dogs = 2;
map<string, Cat> cat_map = 3;
}
message Dog {
string pet_name = 1;
int32 age = 2;
}
message Cat {
string name = 1;
int32 years = 2;
string favorite_food = 3;
}
支持特性包括:
- enum 枚举类型
- repeated 表示列表结构
- map<K,V> 实现键值对存储
4.3 编译生成代码
执行构建后,系统将自动生成对应 Java 类文件。建议大型项目将 .proto 文件独立为一个模块以加速编译。
4.4 数据序列化与反序列化操作
使用生成的类进行数据处理:
val dogA = Dog.newBuilder()
.setPetName("旺仔")
.setAge(2)
.build()
val dogB = Dog.newBuilder()
.setPetName("小黄")
.setAge(4)
.build()
val catA = Cat.newBuilder()
.setName("花花")
.setYears(3)
.setFavoriteFood("鱼干")
.build()
val catB = Cat.newBuilder()
.setName("喵喵")
.setYears(500)
.setFavoriteFood("人类")
.build()
val group = AnimalGroup.newBuilder()
.setGroupId(1001)
.addDogs(dogA)
.addDogs(dogB)
.putCatMap("都市", catA)
.putCatMap("异界", catB)
.build()
// 序列化为字节数组
val serializedData = group.toByteArray()
// 反序列化
val parsedGroup = try {
AnimalGroup.parseFrom(serializedData)
} catch (e: InvalidProtocolBufferException) {
null
}
完整功能请参考官方文档及 API 文档。