公司动态
gpb如何处理proto2与proto3:两种Protobuf语法和语义差异完整指南
gpb如何处理proto2与proto3两种Protobuf语法和语义差异完整指南【免费下载链接】gpbA Google Protobuf implementation for Erlang项目地址: https://gitcode.com/gh_mirrors/gpb/gpbgpb 是 Erlang 语言实现的 Google Protocol Buffers 编译器能够完整解析并支持 proto2 与 proto3 两种 Protobuf 语法的编码、解码及 JSON 转换。本文带你快速搞懂这两种语法的核心差异以及 gpb 是如何在内部区分并正确处理它们的。 proto2 与 proto3 的核心区别一图看懂对比项proto2proto3字段出现方式显式required/optional/repeated字段隐式 optional无required默认值声明支持defaultx不支持自定义默认值编码行为已设置的字段一律写入二进制等于类型默认值的字段不写入二进制解码行为缺失字段可判定为未设置缺失字段直接还原为类型默认值显式optional支持支持自 protobuf 3.12 起实验性引入一句话总结proto3 用值是否等于默认值代替了字段是否被设置这是两种语义最本质的差异。 gpb 内部如何区分两种语法gpb 解析.proto文件时会记录文件的syntax声明并用proto3_msgs项标记哪些 message 属于 proto3。在 gpb 的 proto 定义内部格式proto-defsv2 版本中proto3 普通标量字段的occurrence被表示为defaulty带默认值语义而显式标记optional的 proto3 字段仍为occurrenceoptional表示按 proto2 式的字段存在性处理。这样在生成编解码代码时只需看occurrence就能判断处理方式无需再额外检查该 message 是否属于 proto3。相关细节可参考 doc/dev-guide/proto-defs-versions.md 对应的开发文档。⚙️ 编解码行为差异详解编码encodeproto2只要字段被设置即使值等于默认值就会序列化进二进制proto3只有值不等于类型默认值如 0、空串、false时才写入否则被跳过以节省带宽。解码decodeproto2二进制中没有的 optional 字段解码结果中该字段为undefined你可以据此判断字段确实没被发送proto3没有的字段直接解码为类型默认值无法区分发送了默认值和根本没发送。特例子消息与 oneof 字段proto3 中子消息和oneof字段没有类型默认值因此未设置与设置为空在编码和解码层面都能被区分开——这是 proto3 下少数仍能表达字段存在性的场景。️ 如何用 gpb 编译选项调节 proto2 的解码行为gpb 默认让 proto2 的缺失 optional 字段解码为undefined但提供了两个编译选项改变这一行为定义见src/gpb_compile.erl编译选项效果不加任何选项缺失字段 →undefined可判断字段是否在场defaults_for_omitted_optionals缺失字段 →defaultx声明值未声明则仍为undefined再加type_defaults_for_omitted_optionals缺失字段 → 类型默认值如 uint32 为 0例如对optional uint32 a 1 [default33]的字段空二进制解码结果可分别是aundefined、a33、a0三种。 取舍原则要么能判断字段是否在场要么能直接读到默认值二者不可兼得——这是 Erlang 记录/映射数据模型与 Protobuf 语义权衡的结果。 新手实用建议清单需要感知缺失时如果 proto3 字段需要区分未发送和发送了默认值官方推荐做法是自行定义has_field布尔字段或改用 well-known wrapper 类型如google.protobuf.UInt32Value。显式optionalproto3 中显式标记optional的字段gpb 按 proto2 语义处理——记录中未设置即为undefined映射中则直接省略该键。well-known typesgpb 内置的 proto3 标准类型定义存放在priv/proto3/google/protobuf/目录如any.proto、timestamp.proto、wrappers.proto等可直接 import 使用。maps 模式使用-maps选项生成 Erlang 映射而非记录时proto3 未设置字段默认从映射中省略可用maps_unset_optional选项改为保留undefined值。互操作性gpb 生成的编解码代码与 Google 官方 protoc 生成的二进制格式完全兼容两种语法混排、跨语言通信均无障碍。 相关源码与文档位置语法解析含 proto2/proto3 的msg_elem语法规则src/gpb_parse.erl编码器/解码器代码生成src/gpb_gen_encoders.erl、src/gpb_gen_decoders.erlproto3 默认值语义处理src/gpb_lib.erl、src/gpb_defs.erldefaulty相关逻辑版本化 proto 定义格式说明doc/dev-guide/proto-defs-versions.md编解码行为总览README.mdUnset optionals and the default option 章节掌握以上差异后无论是编写新的.proto文件还是排查跨语言解码不一致的问题你都能准确判断 gpb 的每一个行为是否符合预期。【免费下载链接】gpbA Google Protobuf implementation for Erlang项目地址: https://gitcode.com/gh_mirrors/gpb/gpb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考