我想比较两个消息或(两个子参数)的谷歌协议缓冲区。 我找不到可以实现这一点的API。
有什么想法吗?
我想比较两个消息或(两个子参数)的谷歌协议缓冲区。 我找不到可以实现这一点的API。
有什么想法吗?
在google/protobuf/util目录中引入了新的实用程序函数/类:
- MessageDifferencer:比较两个proto消息并报告它们的差异。
#include <google/protobuf/util/message_differencer.h>
MessageDifferencer::Equals(msg1, msg2);
MessageDifferencer :: Equivalent
而不是Equals
。 - pestophagousMessageDifferencer::Equals
要求参数为 Message
而非 MessageLite
(Message
的派生类)。Equals
需要 GetDescriptor()
函数,而此函数仅在 Message
中实现。因此,在这种情况下,必须选择其他答案中提到的序列化方法,并了解其局限性。 - Antoniogoogle::protobuf::MessageLite
类型,该类型具有比较任何两个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());
}
编辑
正如在下面的评论中指出的那样,特别是对于map
字段,此答案是不正确的。map
元素具有不确定的排序。如果您的消息中可能包含map
字段,请使用MessageDifferencer
。
MessageDifferencer::Equals(msg1, msg2);
更快。 - user875367对于一个名为 foo 的协议缓冲消息实例,以下检查可能会失败:foo.SerializeAsString() == foo.SerializeAsString() 这是由于编码消息时字段顺序的非确定性引起的: https://developers.google.com/protocol-buffers/docs/encoding#order- pooya13
map
字段尤其正确。如果您的protobuf消息可能具有map
字段,则SerializeAsString()
将无法以非确定性方式失败。 - Jake Askeland您可以使用 message.DebugString
,或者您也可以执行以下操作:
std::string strMsg;
message.SerializeToString(&strMsg);
使用两个(二进制)字符串来比较消息,然后进行比较。我没有测试性能,但我认为它比通过.DebugString()返回的可读的消息字符串更快。+您可以使用protobuf-lite库进行此操作(而对于message.DebugString,您需要完整版本)。
协议缓冲区只是某些对象类型的序列化格式。为什么不使用协议缓冲区重建原始对象,然后允许这些对象使用类中构建的任何比较逻辑进行比较呢?
这可能不是最理想的解决方案,但我认为可以通过以下方式实现:
messageA.DebugString() == messageB.DebugString();
除此之外,我认为唯一的解决方案就是创建自己的Message
子类并实现一个bool operator==(const Message&)
。
if (mMessages[i]->body()->GetDescriptor() == T::descriptor())
mMessages是一个带有头部和加密的网络消息池,它使用protobuf主体(google::protobuf::Message*)创建数据包。
因此,为了获得正确类型的消息,我将比较描述符常量指针,该指针对于每种类型的消息都相同(不是100%确定,但到目前为止我没有遇到任何问题)。
这将是比较protobuf消息最快的方法,而无需使用字符串比较,顺便说一句,您可以从描述符中获取类型名称。:-)