1. 概述

Protocol Buffers(Protobuf)和 JSON 是两种主流的数据序列化格式,但在可读性、性能、效率和数据大小方面存在显著差异。

本文将深入对比这两种格式,分析各自的优缺点,帮助你在不同场景下做出合理的技术选型。

2. 可读性与模式要求

Protobuf 强制要求预定义模式(schema)来描述数据结构,这是硬性要求,没有模式文件就无法解析二进制数据。

来看一个典型的 schema.proto 文件示例:

syntax = "proto3";

message User {
  string name = 1;
  int32 age = 2;
  string email = 3;
}

message UserList {
  repeated User users = 1;
}

如果查看 Base64 编码的 Protobuf 消息示例,你会发现它完全不具备人类可读性:

ChwKBUFsaWNlEB4aEWFsaWNlQGV4YW1wbGUuY29tChgKA0JvYhAZGg9ib2JAZXhhbXBsZS5jb20=

应用程序必须结合模式文件才能解析这些数据。

相比之下,JSON 格式表示相同数据时无需严格模式

{
  "users": [
    {
      "name": "Alice",
      "age": 30,
      "email": "alice@example.com"
    },
    {
      "name": "Bob",
      "age": 25,
      "email": "bob@example.com"
    }
  ]
}

而且编码后的数据完全人类可读。

⚠️ 如果项目需要严格验证 JSON 数据,可以使用 JSON Schema,但这属于可选功能,并非强制要求。

3. 模式演进

Protobuf 通过严格模式保证数据完整性,而 JSON 支持“读时模式”(schema-on-read)。两种格式对数据模式演进的支持方式截然不同:

3.1. 消费者的向后兼容性

向后兼容指新代码能解析旧代码序列化的数据。要求新版本能正确反序列化旧版本模式生成的数据。

向后兼容性示意图

实现 JSON 的向后兼容需:

  • ✅ 反序列化时忽略未知字段
  • ✅ 为未设置字段提供默认值

Protobuf 的处理更简单粗暴:

  • ✅ 直接在模式中定义默认值
  • ✅ 模式变更必须遵循最佳实践
    • 新字段必须使用唯一编号
    • 废弃字段需保留编号

虽然两者都支持向后兼容,但 Protobuf 的机制更严格规范。

3.2. 消费者的向前兼容性

向前兼容指旧代码能解析新代码序列化的数据。要求旧版本能正确反序列化新版本模式生成的数据。

向前兼容性示意图

实现向前兼容的关键是:

  • ✅ 旧代码必须忽略未知字段
  • 绝对不能删除必填字段(会破坏兼容性)

JSON 实现方式:

  • ✅ 大多数解析器默认忽略未知字段

Protobuf 天生支持:

⚠️ 踩坑提醒:删除必填字段会同时破坏两种格式的兼容性,正确做法是逐步废弃而非直接删除。

4. 序列化/反序列化与性能

JSON 序列化将对象转换为文本格式,而 Protobuf 将对象转换为紧凑的二进制格式(需符合 .proto 模式定义)。

关键差异点:

  • Protobuf 通过模式文件识别字段名,序列化时无需保存字段名
  • JSON 必须保存完整字段名

Protobuf 在性能和效率上天生优于 JSON

  • ✅ 占用更少存储空间
  • ✅ 序列化/反序列化速度更快(通常快 5-100 倍)

5. 何时使用 JSON

JSON 是 Web API(尤其是 RESTful 服务)的事实标准,主要优势在于:

成熟的生态系统:拥有丰富的工具链和库
JavaScript 原生支持:前后端无缝对接
文本格式易调试:开发阶段排查问题更直观

适用场景:

  1. Web API 交互:RESTful 接口的首选格式
  2. 配置文件:人类可读可编辑的特性使其成为理想选择
  3. 日志系统:无模式特性便于收集多源异构日志
  4. 原型开发:无需特殊客户端,变更成本低

⚠️ 注意:JSON 在高并发场景可能成为性能瓶颈。

6. 何时使用 Protocol Buffers

Protobuf 在存储和网络传输中效率极高,并通过模式定义强制数据完整性。

极致性能:序列化速度快,体积小
严格类型约束:避免运行时类型错误
跨语言支持:官方支持多种编程语言

适用场景:

  1. 实时系统:游戏、金融交易等对延迟敏感的场景
  2. 微服务通信:内部服务间高性能数据传输
  3. 分布式存储:数据库元数据编码(如 HBase/Cassandra)
  4. IoT 设备:资源受限环境下的数据交换

⚠️ 踩坑提醒:使用前需确保团队具备模式管理能力,模式变更需严格遵循兼容性规则。

7. 结论

本文深入分析了 JSON 和 Protobuf 的核心差异,帮助你在制定数据编码策略时做出明智决策。

JSON 的优势场景

  • ✅ 需要人类可读性的场景(API/配置/日志)
  • ✅ 快速原型开发
  • ✅ JavaScript 生态集成

Protobuf 的优势场景

  • ✅ 性能敏感型系统(实时/金融/游戏)
  • ✅ 严格数据完整性要求
  • ✅ 高吞吐量分布式系统

技术选型没有银弹,建议根据具体场景的优先级(性能 vs 灵活性)做出权衡选择。


原始标题:Guide to Choosing Between Protocol Buffers and JSON | Baeldung