网站变灰色统计站老站长推荐草莓
基本映射
1. 基本类型映射
| Protobuf 类型 | JSON 类型 | 示例(Protobuf → JSON) | 说明 |
|---|---|---|---|
int32, sint32, uint32 | 数字 | 123 | 直接映射为 JSON 数字,范围在 -2^31 到 2^32-1 之间。 |
int64, sint64, uint64 | 字符串 | "9223372036854775807" | 必须用字符串表示,避免 JavaScript 等语言中的精度丢失(安全范围为 ±2^53-1)。 |
float, double | 数字 | 3.14 | 浮点数直接映射为 JSON 数字。 |
bool | true/false | true | 布尔值直接映射。 |
string | 字符串 | "hello" | UTF-8 编码的字符串。 |
bytes | 字符串(Base64) | "SGVsbG8gd29ybGQ=" | 二进制数据使用标准 Base64 编码。 |
2. 枚举类型(enum)
枚举类型可以映射为两种形式:
2.1 数值形式(默认)
- Protobuf:
enum Status { ACTIVE = 0; INACTIVE = 1; } - JSON:
{ "status": 0 }或{ "status": 1 }
2.2 字符串形式(需配置)
通过设置 json_format 选项,可将枚举值映射为字符串:
import "google/protobuf/descriptor.proto";extend google.protobuf.EnumValueOptions {string json_name = 50000;
}enum Status {ACTIVE = 0 [(json_name) = "active"];INACTIVE = 1 [(json_name) = "inactive"];
}
- JSON:
{ "status": "active" }或{ "status": "inactive" }
3. 消息类型(message)
- Protobuf:
message Person {string name = 1;int32 age = 2; } - JSON:
{"name": "Alice","age": 30 } - 字段命名转换:Protobuf 的蛇形命名(如
user_name)会自动转换为 JSON 的驼峰命名(如userName),可通过json_name选项自定义。
4. 重复字段(repeated)
- Protobuf:
message Person {repeated string hobbies = 1; } - JSON:
{"hobbies": ["reading", "coding"] }
5. 映射字段(map)
- Protobuf:
message Person {map<string, string> metadata = 1; } - JSON:
{"metadata": {"role": "admin","level": "expert"} }
6. 特殊类型(google.protobuf 包)
6.1 Timestamp
- Protobuf:
import "google/protobuf/timestamp.proto";message Event {google.protobuf.Timestamp time = 1; } - JSON:ISO 8601 格式的字符串
{"time": "2023-01-01T12:00:00Z" }
6.2 Duration
- Protobuf:
import "google/protobuf/duration.proto";message Task {google.protobuf.Duration timeout = 1; } - JSON:带单位的字符串
{"timeout": "3600s" // 或 "1h"、"1.5h" 等 }
6.3 Any
用于包装任意 Protobuf 消息:
- Protobuf:
import "google/protobuf/any.proto";message Response {google.protobuf.Any data = 1; } - JSON:
{"data": {"@type": "type.googleapis.com/your.package.MessageType","field1": "value1","field2": "value2"} }
6.4 Struct
动态结构(类似 JSON 对象):
- Protobuf:
import "google/protobuf/struct.proto";message Config {google.protobuf.Struct settings = 1; } - JSON:直接嵌套 JSON 对象
{"settings": {"debug": true,"timeout": 3000} }
7. 空值处理
- 默认值:未设置的字段在 JSON 中可以省略(如
int32默认为0,string默认为空字符串)。 - 显式空值:通过
google.protobuf.NullValue类型表示null:import "google/protobuf/wrappers.proto";message OptionalField {google.protobuf.StringValue name = 1; // 允许 null }{"name": null }
特殊映射
1. 超出 JavaScript 安全范围的数值类型
| Protobuf 类型 | JSON 类型 | 原因 |
|---|---|---|
int64, sint64 | 字符串 | 范围为 -2^63 到 2^63-1,超过 JavaScript 的安全整数范围 ±2^53-1。 |
uint64 | 字符串 | 范围为 0 到 2^64-1,同样超出 JavaScript 安全范围。 |
fixed64, sfixed64 | 字符串 | 64 位固定宽度整数,也会被转为字符串。 |
2. 二进制类型
| Protobuf 类型 | JSON 类型 | 原因 |
|---|---|---|
bytes | 字符串(Base64) | JSON 无法直接表示二进制数据,需通过 Base64 编码转换为字符串。 |
3. Google Protobuf 标准类型
| Protobuf 类型 | JSON 类型 | 示例格式 |
|---|---|---|
google.protobuf.Timestamp | 字符串 | 2023-01-01T12:00:00Z(ISO 8601 格式) |
google.protobuf.Duration | 字符串 | 3600s、1.5h、5m30s(带单位的字符串) |
google.protobuf.Any | 对象 | { "@type": "...", "field": "value" }(包含类型信息) |
google.protobuf.Struct | 对象 | 直接映射为 JSON 对象(用于动态结构) |
google.protobuf.Value | 任意类型 | 根据实际值类型(如 { "numberValue": 123 }) |
google.protobuf.ListValue | 数组 | JSON 数组(用于动态列表) |
4. 其他特殊情况
4.1 枚举类型
- 默认映射为 数值(如
{ "status": 1 })。 - 可通过
json_name选项配置为 字符串(如{ "status": "ACTIVE" })。
4.2 空值(Null)
- 使用
google.protobuf.NullValue表示null:{"optionalField": null }
4.3 浮点特殊值
NaN、Infinity、-Infinity在 JSON 中通常用字符串表示(如"NaN"),但具体实现可能因语言而异。
为什么这些类型需要特殊处理?
- 跨语言兼容性:JavaScript、Python 等语言的数值类型范围与 Protobuf 不匹配,需要通过字符串避免精度丢失。
- 格式标准化:时间、持续时间等类型通过固定格式(如 ISO 8601)确保不同系统间正确解析。
- 类型信息保留:
Any类型需要在 JSON 中保留原始消息的类型信息(通过@type字段)。
总结
gRPC 的 JSON 映射规则在保持 Protobuf 强类型特性的同时,通过特殊转换确保与 JSON 弱类型系统的兼容性。这些规则是跨平台 API 开发的基础,特别是在处理跨语言数据交换时尤为重要。
