has_field()方法如何与protobuf中的默认值相关联?

Edw*_*per 23 protocol-buffers

我正在尝试确定默认值与在各种编程接口中声明的has_foo()方法之间的关系.特别是,我试图确定在什么情况下(如果有的话)你可以"明确地设置为默认值的字段与未设置值之间的差异".

  1. 如果我明确地将字段(例如"Bar.foo")设置为其默认值(例如,零),那么Bar :: has_foo()保证为该数据结构返回true吗?(对于C++生成的代码,从快速检查看来似乎也是如此,但这并不意味着它得到保证.)如果这是真的,则可以区分显式设置的默认值和序列化之前的未设置.

  2. 如果我明确地将字段设置为其默认值(例如,零),然后序列化该对象并通过线路发送它,是否将发送该值?如果不是,那么显然任何接收此对象的代码都无法区分显式设置的默认值和未设置的值.即,在序列化之后将无法区分这两种情况 - 两种情况下, Bar :: has_foo()都将返回false.

如果无法区分,如果我想编码一个"可为空"的可选值,那么对protobuf字段进行编码的推荐技术是什么?我想到了几个选项,但看起来都不是很好:(a)添加一个额外的布尔字段来记录字段是否设置,或者(b)使用"重复"字段,即使我在语义上想要一个可选字段 - 通过这种方式,我可以区分无值(长度为零的列表)或设置值(长度为一的列表).

Jes*_*erE 30

以下适用于'proto2'语法,而不是'proto3':

设置或不设置字段的概念是Protobuf核心功能.如果将字段设置为值(任何值),则相应的has_xxx方法必须返回true,否则API中存在错误.

如果未设置字段然后序列化消息,则不会为该字段发送任何值.接收方将解析消息,发现包含的值,并设置相应的"has_xxx"值.

具体如何以有线格式实现这一点在此处记录:http://code.google.com/apis/protocolbuffers/docs/encoding.html.短版本是该消息被编码为一系列键值对,并且只有明确设置的字段被包括在编码消息中.

只有在尝试读取未设置字段时,默认值才会起作用.

  • proto2和proto3之间的行为发生了变化.在proto3下,不再有一个单独的"存在"概念.当且仅当它不等于其默认值时,才会在线路上发送字段.(例外是消息类型字段,它仍然遵循proto2行为.) (5认同)
  • 我不认为这是正确的.它没有说明您链接的规范文档中的任何位置:(1)如果成员的值与默认值匹配,则应该对其进行编码.(2)protobuf实现必须允许您区分编码的默认值和解码期间设置的默认值.当另一端的定义已经具有合适的默认值时,通过线路发送空标签+ id是额外的字节.此外,文档甚至声明"如果您的任何元素是可选的,编码的消息可能有也可能没有带有该标记号的键值对." (2认同)