ProtoJSON 格式
Protobuf 支持 JSON 的规范编码,从而更轻松地与不支持标准 protobuf 二进制线格式的系统共享数据。
ProtoJSON 格式不如 protobuf 线格式高效。转换器使用更多的 CPU 来编码和解码消息,并且(除了极少数情况外)编码的消息占用更多空间。此外,ProtoJSON 格式将字段和枚举值名称放入编码消息中,这使得以后更改这些名称变得更加困难。删除字段是一个重大更改,会导致解析错误。简而言之,Google 几乎在所有情况下都更喜欢使用标准线格式而不是 ProtoJSON 格式有很多充分的理由。
在本主题后面的表格中,将按类型逐一描述编码。
当将 JSON 编码的数据解析为协议缓冲区时,如果某个值丢失或其值为 null
,则将其解释为相应的 默认值。
当从协议缓冲区生成 JSON 编码的输出时,如果 protobuf 字段具有默认值并且该字段不支持字段存在,则默认情况下它将从输出中省略。实现可以提供选项以在输出中包含具有默认值的字段。
已设置值并支持字段存在的字段始终在 JSON 编码的输出中包含字段值,即使它是默认值。例如,使用 optional
关键字定义的 proto3 字段支持字段存在,如果设置,则始终显示在 JSON 输出中。任何版本的 protobuf 中的消息类型字段都支持字段存在,如果设置,则会出现在输出中。Proto3 隐式存在标量字段仅在未设置为该类型的默认值时才会出现在 JSON 输出中。
Protobuf | JSON | JSON 示例 | 注释 |
---|---|---|---|
消息 | 对象 | {"fooBar": v, "g": null, ...} | 生成 JSON 对象。消息字段名称映射到 lowerCamelCase 并成为 JSON 对象键。如果指定了 json_name 字段选项,则指定的值将用作键。解析器接受 lowerCamelCase 名称(或 json_name 选项指定的名)和原始 proto 字段名称。null 是所有字段类型都接受的值,并被视为相应字段类型的默认值。但是,null 不能用于 json_name 值。有关详细信息,请参阅 对 json_name 的更严格验证。 |
枚举 | 字符串 | "FOO_BAR" | 使用 proto 中指定的枚举值名称。解析器接受枚举名称和整数值。 |
map<K,V> | 对象 | {"k": v, ...} | 所有键都转换为字符串。 |
repeated V | 数组 | [v, ...] | null 被接受为空列表 [] 。 |
布尔值 | true, false | true, false | |
字符串 | 字符串 | "Hello World!" | |
字节 | Base64 字符串 | "YWJjMTIzIT8kKiYoKSctPUB+" | JSON 值将是使用带填充的标准 Base64 编码作为字符串编码的数据。接受标准或 URL 安全的 Base64 编码(带或不带填充)。 |
int32, fixed32, uint32 | 数字 | 1, -10, 0 | JSON 值将是十进制数字。接受数字或字符串。空字符串无效。 |
int64, fixed64, uint64 | 字符串 | "1", "-10" | JSON 值将是十进制字符串。接受数字或字符串。空字符串无效。 |
float, double | 数字 | 1.1, -10.0, 0, "NaN", "Infinity" | JSON 值将是数字或特殊字符串值之一:"NaN"、"Infinity" 和 "-Infinity"。接受数字或字符串。空字符串无效。指数表示法也被接受。 |
Any | 对象 | {"@type": "url", "f": v, ... } | 如果 Any 包含具有特殊 JSON 映射的值,则将按如下方式转换:{"@type": xxx, "value": yyy} 。否则,该值将转换为 JSON 对象,并且将插入 "@type" 字段以指示实际数据类型。 |
时间戳 | 字符串 | "1972-01-01T10:00:20.021Z" | 使用 RFC 3339,其中生成的输出始终为 Z 规范化,并使用 0、3、6 或 9 个小数位。还接受“Z”以外的偏移量。 |
持续时间 | 字符串 | "1.000340012s", "1s" | 生成的输出始终包含 0、3、6 或 9 个小数位,具体取决于所需的精度,后跟后缀“s”。只要它们适合纳秒精度,就可以接受任何小数位(也不包括),并且需要后缀“s”。 |
结构 | 对象 | { ... } | 任何 JSON 对象。请参阅 struct.proto 。 |
包装类型 | 各种类型 | 2, "2", "foo", true, "true", null, 0, ... | 包装器在 JSON 中使用与包装的原始类型相同的表示形式,除了允许 null 并在数据转换和传输过程中保留它。 |
字段掩码 | 字符串 | "f.fooBar,h" | 请参阅 field_mask.proto 。 |
列表值 | 数组 | [foo, bar, ...] | |
值 | 值 | 任何 JSON 值。有关详细信息,请查看 google.protobuf.Value。 | |
空值 | null | JSON null | |
空 | 对象 | {} | 一个空的 JSON 对象 |
JSON 选项
符合 protobuf JSON 规范的实现可以提供以下选项
始终发出没有存在感的字段:默认情况下,不支持存在感且具有默认值的字段在 JSON 输出中被省略(例如,值为 0 的隐式存在整数、为空字符串的隐式存在字符串字段以及空重复和映射字段)。实现可以提供一个选项来覆盖此行为并输出具有其默认值的字段。
从 v25.x 开始,C++、Java 和 Python 实现不符合规范,因为此标志会影响 proto2 的
optional
字段,但不会影响 proto3 的optional
字段。计划在未来的版本中修复此问题。忽略未知字段:protobuf JSON 解析器应默认拒绝未知字段,但可以提供一个选项来忽略解析中的未知字段。
使用 proto 字段名称而不是 lowerCamelCase 名称:默认情况下,protobuf JSON 打印机应将字段名称转换为 lowerCamelCase 并将其用作 JSON 名称。实现可以提供一个选项来改为使用 proto 字段名称作为 JSON 名称。Protobuf JSON 解析器需要接受转换后的 lowerCamelCase 名称和 proto 字段名称。
将枚举值作为整数而不是字符串发出:默认情况下,JSON 输出中使用枚举值名称。可以提供一个选项来改为使用枚举值的数值。