数据序列化格式全景:JSON、Protobuf、MessagePack 与 Parquet

对比主流数据序列化格式:JSON/XML/YAML/TOML 文本族、Protobuf/MessagePack/CBOR/BSON 二进制族、Parquet/ORC 列式族——schema 演进、性能基准、版本兼容与选型决策树。

引言

数据传输与存储的第一性问题是:用什么格式把对象变成字节,再变回来? 格式选择决定了三件事——体积、速度、演进能力。文本族(JSON/XML/YAML)人可读但费字节;二进制族(Protobuf/MessagePack)省空间但难调试;列式族(Parquet/ORC)为分析而生的压缩率惊人。本文给出全景对比 + 一套可落地的选型决策树。

前置:基本数据模型概念。大数据场景配合 [[database]] / [[data-engineering]] 专题。


目录


1. 序列化格式三大家族

家族代表特点场景
文本族JSON / XML / YAML / TOML人可读、调试易、体积大API、配置、文档
二进制族Protobuf / MessagePack / CBOR / BSON紧凑、快、难读RPC、缓存、物联网
列式族Parquet / ORC / Arrow高压缩、列扫描快大数据分析、数仓

核心取舍:可读性 ↔ 性能 ↔ 演进安全,三者最多兼顾两样。

一个数据「一生」可能跨多种格式:对象在内存(Arrow)→ RPC 线(Protobuf)→ 落盘(Parquet)——按阶段选格式。


2. 文本族:JSON、XML、YAML、TOML

格式类型可读性体积强项
JSON通用数据★★★中API 事实标准、生态最广
XML文档/配置★★大命名空间、Schema(XSD)、工具成熟
YAML配置★★★★中缩进友好、可注释、锚点复用
TOML配置★★★★中表结构清晰、无缩进歧义

JSON 事实标准(API/Web/NoSQL),但有限制:

{
  "user": {"name": "Alice", "age": 30, "active": true}
}

JSON 缺陷:无注释、无数值范围类型(整数/浮点混淆)、日期需约定、null 与缺失难区分。

YAML(K8s/Docker Compose 首选)——缩进与锚点:

defaults: &defaults
  timeout: 30
  retries: 3

service:
  <<: *defaults      # 锚点合并
  name: auth

TOML(Rust/Cargo 风格,无缩进歧义):

[server]
host = "0.0.0.0"
ports = [8000, 8001]
选型推荐
Web APIJSON
配置文件(人写)TOML(简单)或 YAML(复杂树)
带 schema 校验JSON Schema / XSD
文档交换XML

3. 二进制族:Protobuf、MessagePack、CBOR、BSON

Protobuf(gRPC 的默认,Schema 驱动):

message User {
  int64  id = 1;
  string name = 2;
  bool   active = 3;
  repeated string tags = 4;
}
user = User(id=1, name="Alice", active=True, tags=["a", "b"])
data = user.SerializeToString()   # 紧凑二进制
格式Schema特点强项
Protobuf必须(.proto)字段号编码、压缩强gRPC、微服务
MessagePack无JSON 兼容的二进制缓存/Redis、体积敏感
CBOR无RFC 标准、流式物联网、CoAP
BSON无MongoDB 原生文档数据库

MessagePack 与 JSON 等价转换:

JSON: {"name": "Alice", "age": 30}
MsgPack: 0x82 0xa4 'n' 'a' 'm' 'e' 0xa5 'A' 'l' 'i' 'c' 'e' ...

体积对比直观:同样的 {"name":"Alice"}——JSON 约 17 字节,MessagePack 约 12 字节,Protobuf 约 8 字节。


4. 列式族:Parquet 与 ORC

列式存储改变存储布局——按列而不是按行存,分析查询只读需要的列:

格式压缩率适用特点
Parquet极高(列编码 + 字典)Spark/Hive/查询引擎跨生态最广
ORC极高Hive 原生更侧重 Hive 优化
Arrow内存列式进程间零拷贝不是存储,是内存布局

为什么列式适合分析:

行式: [Alice,30,北京] [Bob,25,上海] [Cara,28,广州]
列式: [Alice,Bob,Cara] [30,25,28] [北京,上海,广州]
      ↑ 查询"平均年龄"只读第二列,且同类型压缩率翻倍

Parquet 能力:嵌套结构、谓词下推(只读满足条件的块)、字典编码、Snappy/Gzip/Zstd 压缩。

选型要点:OLTP(事务)用行式,OLAP(分析)用列式——数据仓库、日志分析、特征存储必备。


5. Schema 驱动 vs 无 Schema

维度Schema 驱动(Protobuf/Avro)无 Schema(JSON/MsgPack)
编译期检查✅ 类型安全❌ 运行期才错
演进显式规则(字段号)靠约定
体积小(字段号)大(存键名)
灵活性需改 .proto 重编译即改即用
调试难读二进制直接看文本

Schema 驱动的关键价值——演进安全:id = 1 是永久 ID,字段改名不影响线上兼容(见下节)。

无 Schema 的灵活代价:键名每次都存(体积)、缺字段/多字段无约束、跨服务契约靠口头。

经验:API 边界用 Schema 驱动(Protobuf/Avro),内部处理/调试用无 Schema——边界要契约,内部要效率。


6. 版本演进与兼容策略

Protobuf 演进规则(跨版本兼容的黄金规范):

message User {
  int64  id = 1;      // 永远不要改字段号!
  string name = 2;
  // 新增字段:追加新号
  optional string email = 3;   // 老版本读到会忽略
  // 已删除字段:用 reserved 保留号,防止误用
  reserved 4;
}
场景规则
新增字段追加新字段号,用 optional
删除字段reserved 占位,防未来复用
改名字段号不变即可
改类型危险!旧数据可能解析错
加枚举值通常兼容,需协商

JSON 演进替代:加可选字段(老客户端忽略)、不加必需字段、容忍未知字段。语义版本管理契约。


7. 性能基准:体积与速度对比

(典型微服务消息,越大差异越明显)

格式体积(相对 JSON)序列化速度解析速度
JSON(Gson/Jackson)1.0(基准)1.01.0
MessagePack约 0.6约 1.5×约 1.3×
Protobuf约 0.4约 3–5×约 3–5×
Avro(含 Schema)约 0.45约 3×约 3×
Parquet(压缩)约 0.15–0.3—(列式扫描快)—

差异随消息变大而放大;小消息(<100B)选型差异几乎可忽略——别为「快一点」牺牲可读性。

内存布局对比:Protobuf 无字符串池与指针开销,连续内存布局缓存友好;JSON 解析要建树,GC 压力大。


8. 语言生态与工具链

格式主流库备注
JSONJackson / serde_json / Gson各语言皆有
Protobufprotoc + 各语言插件gRPC 配套
MessagePackmsgpack 各语言与 JSON 类型互通
Parquetarrow / pyarrow大数据生态统一
AvroPython avro / JavaKafka 常用
YAMLPyYAML / snakeyamlK8s 配置

工具链建议:JSON Schema 校验 + OpenAPI 文档 = 无 Schema 时代的「轻契约」;Protobuf 用 buf 做 lint/breaking 检查。


9. 选型决策树

数据要给人看吗?
├─ 是 → JSON(API) / YAML(配置) / TOML(简单配置)
└─ 否 → 数据会跨版本长期演进吗?
    ├─ 是 → Protobuf(gRPC/RPC) 或 Avro(Kafka/流)
    └─ 否 → 体积敏感吗?
        ├─ 是 → MessagePack / CBOR
        └─ 否 → JSON 就行

分析型查询为主?
└─ 是 → Parquet(数仓/Spark) / ORC(Hive)

决策因子权重:可调试性 > 生态成熟度 > 性能 > 体积 > 演进复杂度——多数场景 JSON 起步,高流量边界升级 Protobuf。


10. 速查表

需求格式
Web APIJSON + OpenAPI
配置TOML / YAML
RPC/微服务Protobuf + gRPC
Kafka/流式Avro + Schema Registry
缓存体积敏感MessagePack / CBOR
MongoDBBSON
数仓分析Parquet / ORC
进程内列式Arrow
文档/多命名空间XML

一句话记忆:给人看用 JSON,给机器省用 Protobuf,给分析引擎用 Parquet;三族各司其职,格式随阶段流动。


延伸阅读

  • /regex-deep-dive/ — 文本处理的底层工具
  • /text-processing-toolkit/ — jq 处理 JSON 的命令行实战
  • [[data-engineering]] — 大数据管道的存储格式选择
  • [[database]] — 存储引擎与数据类型的关系

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「others」更多文章

  1. 通配符与 Glob 匹配:与正则的分野与落地
  2. 算法复杂度速查:Big-O、空间复杂度与工程直觉
  3. 正则表达式深层解析:引擎、回溯与灾难性回溯