中文内容选序列化格式,别只看压缩率:JSON、XML 与 Protobuf 实测对比
Photo: Addshore, CC BY-SA 4.0, via Wikimedia Commons
每逢技术选型,序列化格式的对比文章一搜一大把。但绝大多数基准测试用的都是英文样本数据——而中文有一个天然特点:在 UTF-8 下,一个汉字占 3 个字节,是英文字母的 3 倍。这个特性会实质性地影响各格式的表现,尤其是体积和压缩收益。
我们用一份混合语料(产品描述、用户评论、含 Emoji 的社交文本)做了几组实测,结论比想象中有趣。
体积:差距没有想象中大,但压缩会洗牌
同一份含大量中文的 JSON 文档:
- JSON(UTF-8):基准。
- XML:比 JSON 大 25%–40%。中文内容本身两者一样大(都是 UTF-8),差距全来自标签名——而标签名通常是英文,反而被中文内容「稀释」了。语料越偏中文,XML 的劣势越小。
- Protobuf:原始编码比 JSON 小 40%–60%,主要赢在字段名被替换成编号、数字用变长整数。
- JSON + Gzip:压缩后与 Protobuf + Gzip 的差距缩小到 10%–15% 以内。中文冗余度高,压缩效果格外好。
要点:如果你的流量走 HTTPS 且开启压缩(大多数场景都是),JSON 和 Protobuf 的体积差距会被大幅抹平,这时候体积不该是你选 Protobuf 的首要理由。
多语言字符:三者都支持 UTF-8,但细节有坑
- JSON:标准要求 UTF-8,Emoji 和中文都没问题。坑在于个别老客户端默认按 GBK 解析响应头没声明 charset 的响应——服务端务必显式返回
Content-Type: application/json; charset=utf-8。 - XML:靠 XML 声明
<?xml version="1.0" encoding="UTF-8"?>,声明和实际编码不一致时会直接解析失败。历史遗留系统里这是中文乱码的重灾区。 - Protobuf:
string类型规定必须是 UTF-8,二进制安全,理论上最稳。但调试时你会看到大量不可读字节,中文可读性为零。
调试与协作:这是 JSON 的主场
坦白说,这一项没有悬念。用 curl 打一个返回 JSON 的接口,人眼直接可读;Protobuf 需要配合 .proto 文件和专用工具才能解读;XML 介于两者之间——可读但啰嗦。
对面向中国用户的业务来说还有一层:联调成本。前端、后端、测试三方都改一份 .proto 文件的流程,在快节奏业务迭代里经常成为摩擦点。Protobuf 的强 Schema 是优点也是枷锁,取决于你的团队协作模式。
生态兼容:看你的边界在哪
- 纯内部微服务、gRPC 体系:Protobuf 生态成熟,选它没毛病。
- 对外 API、Webhook、第三方回调:JSON 是事实标准,别为难你的集成方。
- 金融、政企等老系统对接:XML 依然常见,SOAP 还活着。
一张决策树
- 对外暴露 API? → JSON,没有讨论余地。
- 内部 gRPC 微服务、QPS 高、字段多? → Protobuf。
- 需要对接遗留 SOAP / 政企系统? → XML,配合严格的 UTF-8 声明。
- 其他情况? → JSON + Gzip,把省下的时间花在业务上。
最后说一句面试视角:如果面试官问「为什么你们用 JSON 而不是 Protobuf」,一个加分的回答不是背参数对比,而是像上文这样说出「压缩已开启时体积差距收窄、调试成本、团队协作摩擦」这三层权衡。选型题考的从来不是哪个格式更快,而是你能不能讲清楚为什么这个选择适合你的场景。