数据格式大乱斗:JSON、MessagePack、Protobuf
你写程序的时候有没有遇到过这个问题:想把一个对象从后端发给前端,或者从服务A传给服务B,该用什么格式?
大多数人第一反应是 JSON。它简单、通用、谁都能读。但 JSON 有个毛病——太啰嗦。
比如一个简单的用户信息:
{
"name": "张三",
"age": 28,
"email": "zhangsan@example.com"
}
用字节数来算,这段 JSON 大约 60 字节。但如果换成二进制格式,同样信息可能只要 20 字节左右。
今天就来聊聊 JSON 的两个竞争对手:MessagePack 和 Protobuf。它们都在解决同一个问题——更高效地传输数据。
JSON:所有人都认识的通用语言
JSON(JavaScript Object Notation)是互联网上最流行的数据格式。它的特点就三个词:简单、可读、通用。
{"user_id": 1001, "status": "active", "score": 95.5}
优点:
- 几乎所有人都能看懂,调试方便
- 所有语言都有现成的解析库
- 和 REST API 是天然搭档
缺点:
- 文本格式,包含大量冗余(引号、花括号、字段名重复)
- 解析速度相对较慢
- 不支持复杂的类型(日期、二进制数据都要转字符串)
适合场景: API 接口、配置文件、人类可读的数据交换。
MessagePack:JSON 的"瘦身版"
MessagePack 的口号是"JSON 的二进制等价物"。它的设计目标很简单:结构和 JSON 一样,但体积更小、解析更快。
同样的数据,MessagePack 的序列化结果:
\xA3\x75\x73\x65\x72 // "user" (字符串)
\x01 // 1 (整数)
优点:
- 体积通常比 JSON 小 30%~50%
- 解析速度快 2~3 倍
- 支持更多数据类型(二进制、日期、大整数)
- 不需要预定义 schema,上手简单
缺点:
- 二进制格式,直接看是乱码
- 生态不如 JSON 广泛
- 字段名仍然需要完整传输(虽然用了更紧凑的编码)
适合场景: 内部服务间通信、缓存数据序列化、对性能有要求但又不想引入复杂 schema 的项目。
Protobuf:谷歌的"专业级"方案
Protobuf(Protocol Buffers)是谷歌开源的一套二进制序列化框架。它和 MessagePack 最大的区别在于:你需要先定义一个 .proto 文件,描述数据的结构。
message User {
int32 user_id = 1;
string name = 2;
bool is_active = 3;
}
用这个定义生成的二进制数据:
08 96 07 // user_id = 1001
12 06 7A // name = "zhangsan" (字段2)
18 01 // is_active = true (字段3)
优点:
- 体积最小(字段用数字编号代替名字,节省大量空间)
- 解析速度最快
- 强类型约束,错误早发现
- 向后兼容性好(新增字段不影响旧代码)
- 支持代码生成(多种语言一键出模型)
缺点:
- 需要学习 proto 语法
- 调试不便(二进制格式)
- 多一步编译流程
- 过度设计——简单场景用 Protobuf 有点杀鸡用牛刀
适合场景: 微服务间通信、高性能要求的数据传输、需要严格类型约束的大型项目、gRPC 框架的搭档。
三者对比:一张表说清楚
| 维度 | JSON | MessagePack | Protobuf |
|---|---|---|---|
| 可读性 | ⭐⭐⭐ 文本格式,直接可读 | ⭐ 二进制,需工具解码 | ⭐ 二进制,需工具解码 |
| 体积 | 基准 | 比 JSON 小 30%~50% | 比 JSON 小 50%~70% |
| 解析速度 | 慢 | 中等 | 快 |
| 类型支持 | 基本类型 | 较好 | 完整类型系统 |
| 学习成本 | 零 | 低 | 中等 |
| Schema 要求 | 不需要 | 不需要 | 需要定义 .proto |
| 生态成熟度 | 最高 | 中等 | 高(谷歌背书) |
| 向后兼容 | 靠约定 | 靠约定 | 语言级支持 |
怎么选?看这三个问题
1. 数据要不要给人看?
- 要 → 选 JSON
- 不要 → 继续看
2. 有没有复杂的类型需求?
- 没有,就是简单的键值对 → 选 MessagePack
- 有,需要严格的类型约束和版本管理 → 选 Protobuf
3. 性能要求有多高?
- 一般(普通 API 调用)→ MessagePack 够用了
- 很高(每秒几万条消息)→ Protobuf 更合适
实际案例:什么时候该换格式
API 接口:继续用 JSON。前端要能读懂,开发者要能调试,没必要折腾。
微服务内部通信:考虑 MessagePack 或 Protobuf。服务之间不需要人肉读,追求效率和规范。
缓存序列化:MessagePack 很合适。Redis 里存的复杂对象,用 MessagePack 序列化后体积小、速度快。
实时数据流:Protobuf + gRPC 是黄金组合。流式传输、强类型、高性能,一站式解决。
总结
JSON 是互联网的普通话——谁都能说,虽然不够高效。MessagePack 是精简版普通话——保留通用性,去掉冗余。Protobuf 是专业外语——需要学习,但用好了效率拉满。
你的项目不需要三个都上。想清楚数据给谁看、性能要求有多高、团队有没有经验,就能做出合适的选择。