覆盖protobuf中的重复字段MergeFrom与MergeFromString

时间:2016-11-10 16:22:39

标签: c++ protocol-buffers

假设我将proto定义为:

MyProto {
    optional MyWrapper wrapper = 1;
}

其中:

MyWrapper {
    repeated int32 data = 1;
}

当我在MergeFromString的两个文本规范上调用MyProto时,包装器中重复字段的两个版本被连接(一个附加到另一个。)我真的希望它们被覆盖代替。 MergeFromString的文档说:

  

当我们在| serialized |中找到一个字段时这已经存在于此   消息:

     
      
  • 如果是"重复"字段,我们附加到列表的末尾。
  •   
  • 否则,如果它是标量,我们会覆盖我们的字段。
  •   
  • 否则,(它是一个非重复的复合词),我们递归合并   进入现有的复合材料。
  •   

显然,使用包装器,我们正在讨论第三种情况。所以我们递归合并,在下一次复飞时,我们看到一个重复的字段,并将值附加到目标。所以我明白为什么会这样。

将此与MergeFrom的规范进行比较:

  

此方法将指定消息的内容合并到   当前的消息。在指定消息中设置的奇异字段   覆盖当前消息中的相应字段。重复   字段被追加。奇异的子消息和组是递归的   合并。

在这种情况下,包装字段不是单个字段,并且不会覆盖包装器吗?

所以我的问题是双重的,

1)这是不一致的,还是我误解了什么?

2)当我致电MergeFromString时,如何获得所需的覆盖行为,而不是合并重复的字段?

1 个答案:

答案 0 :(得分:2)

对于问题的第一部分,您引用的MergeFrom规范在技术上是正确的,尽管措辞有些令人困惑。它说“奇异字段”被覆盖但是“单个子消息”被递归合并,并且你的包装器将被认为是一个单一的子 消息。

要获得所需的行为,您应该可以使用FieldMaskUtil。特别是,您可以调用FieldMaskUtil::MergeMessageTo(...)并传递MergeOptions配置为替换重复字段而不是连接它们。为此,您首先必须从文本格式表示中解析这两条消息。