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

Chr*_*ris 3 c++ protocol-buffers

假设我有一个 proto 定义为:

MyProto {
    optional MyWrapper wrapper = 1;
}
Run Code Online (Sandbox Code Playgroud)

在哪里:

MyWrapper {
    repeated int32 data = 1;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果它是一个“重复”字段,我们将附加到列表的末尾。
  • 否则,如果它是标量,我们将覆盖我们的字段。
  • 否则,(它是一个非重复的组合),我们递归地合并到现有的组合中。

显然,对于包装器,我们谈论的是第三种情况。所以我们递归地合并,在下一次循环中,我们看到一个重复的字段,值被附加到目标。所以我明白为什么会这样了。

将此与以下规范进行比较MergeFrom

此方法将指定消息的内容合并到当前消息中。指定消息中设置的单个字段会覆盖当前消息中的相应字段。附加重复的字段。单个子消息和组被递归合并。

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

所以我的问题是双重的,

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

2)如何在调用时获得所需的覆盖行为而不是合并重复字段MergeFromString

小智 5

对于您问题的第一部分,您MergeFrom引用的规范在技术上是正确的,尽管措辞有点混乱。它说“单一字段”被覆盖,但“单一子消息”被递归合并,并且您的包装器将被视为单一子消息。

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

  • 但是字段掩码实用程序仅适用于消息中存在的重复字段,而不适用于子消息中 (2认同)