谷歌协议缓冲比较

dim*_*mba 26 c++ protocol-buffers

我想比较Google协议缓冲区的两个消息或(两个子参数).我没有找到实现它的API.

有任何想法吗?

Ami*_*iga 29

你可以使用google :: protobuf :: util :: MessageDifferencer这个类.我认为它仅在v3.0.2之后可用:

在google/protobuf/util目录中引入了新的实用程序函数/类:

  • MessageDifferencer:比较两个原型消息并报告它们的差异.

MessageDifferencer::Equals(msg1, msg2);

  • 要添加:MessageDifferencer仅适用于C++ (3认同)
  • 根据您的 Message 类型中的字段是否可以具有默认值,您可能需要考虑 `MessageDifferencer::Equivalent` 而不是 `Equals` (3认同)
  • 请注意,不幸的是,如果您使用的是该库的精简版本,则这不起作用,因为“MessageDifferencer::Equals”要求参数为“Message”而不是“MessageLite”(“Message”派生自“MessageLite”)。`Equals` 需要 `GetDescriptor()`,这是一个仅在 `Message` 中实现的功能。因此,在这种情况下,人们必须采用其他答案中提到的序列化方法之一,并充分意识到其局限性。 (2认同)

Lor*_*ler 7

而不是使用message.DebugString你也可以做

std::string strMsg;
message.SerializeToString(&strMsg);
Run Code Online (Sandbox Code Playgroud)

用两个消息然后比较两个(二进制)字符串.我没有测试性能,但我认为它比比较.DebugString()返回的人类可读消息字符串更快.+您可以使用protobuf-lite库(对于message.DebugString,您需要完整版本).

  • 不能保证序列化在二进制文件之间以及随着时间的推移是一致的。例如,二进制文件未知的扩展名将在已知扩展名之后最后序列化(作为未知字段)。因此,序列化将取决于序列化时可用的描述符。因此,比较序列化的消息很不利于检查是否相等。MessageDifferencer是执行此操作的正确方法。 (5认同)

Jak*_*and 7

您可以依赖于所有protobuf消息都继承自该google::protobuf::MesageLite类型的事实,而这种消息又包含了比较任何两个protobuf消息所需的一切,无论它们是否是相同的派生类型:

bool operator==(const google::protobuf::MessageLite& msg_a,
                const google::protobuf::MessageLite& msg_b) {
  return (msg_a.GetTypeName() == msg_b.GetTypeName()) &&
      (msg_a.SerializeAsString() == msg_b.SerializeAsString());
}
Run Code Online (Sandbox Code Playgroud)

  • 从他们的文档中:>对于协议缓冲区消息实例foo,以下检查可能失败:foo.SerializeAsString()== foo.SerializeAsString()这是由于编码消息时字段顺序的不确定性:https:// developers .google.com / protocol-buffers / docs / encoding#order (2认同)

Gia*_*nni -1

这可能不是理想的解决方案,但我认为可以通过以下方式来完成:

messageA.DebugString() == messageB.DebugString();
Run Code Online (Sandbox Code Playgroud)

除此之外,我认为唯一的解决方案是创建您自己的Message子类并实现bool operator==(const Message&).

  • @Yousf 正如 Protobuf 文档所说,从 Message 继承并不是正确的方法。我同意这一点,因为您必须更改协议生成的文件,因此更改原始协议将很困难,因为您必须在**每次**编译时更改它。 (3认同)