在protobuf 2中编码"可空"字段的首选方法是什么?

Edw*_*per 8 protocol-buffers

我正在定义一个ProtoBuf消息,我想要一个"可以为空"的字段 - 即,我想要区分具有值而没有值的字段.举一个具体的例子,假设我有"x"和"y"字段来记录某个对象的坐标.但在某些情况下,坐标是未知的.下面的定义将无法正常工作,因为如果x或y是不确定的,那么他们默认为零(这是一个有效的值):

message MyObject {
    optional float x = 1;
    optional float y = 2;
}
Run Code Online (Sandbox Code Playgroud)

一种选择是添加一个布尔字段,记录相应字段的值是否已知.即:

message MyObject {
    optional bool has_x = 1; // if false, then x is unknown.
    optional bool has_y = 2; // if false, then y is unknown.
    optional float x = 3; // should only be set if has_x==true.
    optional float y = 4; // should only be set if has_y==true.
}
Run Code Online (Sandbox Code Playgroud)

但这会增加一些额外的簿记 - 例如,当我设置x字段的值时,我必须始终记住也设置has_x.另一种选择是使用列表值,其中列表总是长度为0或长度为1:

message MyObject {
    repeated float x = 1; // should be empty or have exactly 1 element.
    repeated float y = 2; // should be empty or have exactly 1 element.
}
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,定义似乎有点误导,界面并没有好多少.

有没有第三种选择我没有想到比这两种更好?你是如何处理在protobuf中存储可空字段的?

Jes*_*erE 5

Protobuf 2消息具有“空字段”的内置概念。C ++接口包含一些方法has_xxxclear_xxx用于分别检查是否已设置该字段和取消设置该字段。

由于使用“标签”在消息中对字段进行编码的方式,此功能“免费”出现。未设置字段仅在编码消息中“不存在”。

Proto 3不具有此功能,而是将任何缺少的字段设置为其默认值

  • JesperE的答案过去可能是正确的,但现在绝对不再正确。 (4认同)
  • 是。您应该阅读有关protobuf消息的编码方式的信息:http://code.google.com/apis/protocolbuffers/docs/encoding.html。消息被编码为一系列键/值对(这是每个字段上的标识符/标记的作用)。未设置字段只是编码消息中不存在。如果您分别具有标签分别为1、2和3的三个字段a,b和c,并且仅对将“ a”设置为“ 42”的消息进行编码,则编码后的消息将包含“ field(1)= 42英寸,仅此而已。 (2认同)