本文翻译自 ProtoJSON Format | Protocol Buffers Documentation

Protobuf 支持规范的 JSON 编码格式,便于与不支持标准 Protobuf 二进制有线格式的系统共享数据。

ProtoJSON 格式不如 Protobuf 有线格式高效。转换器在编解码消息时会消耗更多 CPU 资源,且(除少数情况外)编码后的消息占用空间更大。此外,ProtoJSON 格式会将字段名和枚举值名写入编码消息,导致后续重命名这些标识符变得极其困难。删除字段更是破坏性变更,会引发解析错误。简言之,Google 坚持使用标准有线格式而非 ProtoJSON 格式有诸多充分理由。

下文表格按类型详细描述了编码规则。

解析与生成规则

将 JSON 编码数据解析为 Protocol Buffer 时:

从 Protocol Buffer 生成 JSON 编码数据时:


JSON 数据表示对照表

Protobuf 类型 JSON 类型 JSON 示例 说明
message object {"fooBar": v, "g": null, ...} • 字段名转换为小驼峰命名(lowerCamelCase)作为 JSON 键
• 若指定 json_name 字段选项,则使用该值作为键
• 解析器同时接受小驼峰名(或 json_name 值)和原始字段名
null 会被解释为字段默认值
• ⚠️ json_name 禁止设为 null(详见严格校验说明
enum string "FOO_BAR" • 使用 proto 定义的枚举值名
• 解析器同时接受枚举名和整数值
map<K,V> object {"k": v, ...} 所有键均转换为字符串
repeated V array [v, ...] null 等价于空列表 []
bool boolean true, false -
string string "Hello World!" -
bytes base64 string "YWJjMTIzIT8kKiYoKSctPUB+" • 输出:标准 base64 编码(含填充)
• 输入:接受标准/URL安全 base64(含/不含填充)
int32, fixed32, uint32 number 1, -10, 0 • 接受数字或字符串
• 空字符串无效
int64, fixed64, uint64 string "1", "-10" • 接受数字或字符串
• 空字符串无效
float, double number/string 1.1, "NaN", "-Infinity" • 接受数字或特殊字符串("NaN"/"Infinity"/"-Infinity")
• 支持科学计数法
• 空字符串无效
Any object {"@type": "url", "value": yyy} 含特殊 JSON 映射的值按固定结构转换,其他值转换后插入 "@type" 字段标识类型
Timestamp string "1972-01-01T10:00:20.021Z" • 输出:RFC 3339 格式(Z 标准化,含 0/3/6/9 位小数)
• 输入:接受非 "Z" 时区偏移
Duration string "1.000340012s" • 输出:含 0/3/6/9 位小数 + "s" 后缀
• 输入:接受任意精度纳秒值 + "s" 后缀
Struct object { ... } 任意 JSON 对象(参见 struct.proto
Wrapper types 对应基础类型 2, "foo", true, null 包装类型使用原始类型表示规则,但允许保留 null
FieldMask string "f.fooBar,h" 参见 field_mask.proto
ListValue array [foo, bar, ...] -
Value any 任意值 任意 JSON 值(详见 google.protobuf.Value
NullValue null null JSON null
Empty object {} 空 JSON 对象

JSON 选项 {#json-options}

符合规范的 Protobuf JSON 实现可提供以下选项:

始终输出无存在性字段

忽略未知字段

使用 proto 字段名替代小驼峰命名

枚举值输出为整数