8

简而言之,有没有办法定义一个包含另一个任意类型消息的 protobuf 消息?就像是:

message OuterMsg {
    required int32 type = 1;
    required Message nestedMsg = 2; //Any sort of message can go here
}

我怀疑有一种方法可以做到这一点,因为在各种 protobuf 实现中,编译的消息从一个公共Message基类扩展而来。

否则我想我必须为这样的各种消息创建一个通用的基本消息:

message BaseNestedMessage {
    extensions 1 to max;
}

然后做

message OuterMessage {
    required int32 type = 1;
    required BaseNestedMessage nestedMsg = 2;
}

这是实现这一目标的唯一方法吗?

4

3 回答 3

9

最流行的方法是为每种消息类型创建可选字段:

message UnionMessage
{
    optional MsgType1 msg1 = 1;
    optional MsgType2 msg2 = 2;
    optional MsgType3 msg3 = 3;
}

该技术也在 Google 官方文档中进行了描述,并且在各种实现中得到了很好的支持: https ://developers.google.com/protocol-buffers/docs/techniques#union

于 2012-08-30T08:48:03.803 回答
7

基本上不是直接的;protocol buffers 很想提前知道结构,而且消息的类型不包括在线路上。公共Message基类是提供公共管道代码的实现细节——协议缓冲区规范不包括继承。

因此,选择有限:

  • 每个消息类型使用不同的字段编号
  • 单独序列化消息,并将其作为bytes类型包含,并传达“这是什么?” 信息分开(大概是一个鉴别器/枚举)

我还应该注意,一些实现可能会为此提供更多支持;protobuf-net (C# / .NET) (分别)支持继承和动态消息类型(即您上面所拥有的),但这主要用于仅从那个库到那个库。因为这都是对规范的补充(就有线格式而言仍然 100% 有效),因此从其他实现中解释此类数据可能会不必要地混乱。

于 2012-08-30T08:16:07.340 回答
2

optional作为多个字段的替代方案,该oneof关键字可以从Protocol Buffers的 v2.6 开始使用。

message UnionMessage {
  oneof data {
    string a = 1;
    bytes b = 2;
    int32 c = 3;
  }
}
于 2015-04-24T10:38:31.547 回答