Protobuf: 嵌套任意类型的消息

8
简而言之,是否有一种方法可以定义一个包含任意类型另一个消息的protobuf消息?就像这样:
```proto message MyMessage { google.protobuf.Any any_field = 1; } ```
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;
}

这是唯一的实现方式吗?

3个回答

10

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

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

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


7
基本上而言,协议缓冲区需要预先知道结构,并且消息类型不会包含在线路上。通用的Message基类是提供公共管道代码的实现细节,协议缓冲区规范不包括继承。
因此,有限的选项如下:
  • 使用不同的字段编号 per 消息类型
  • 将消息单独序列化,并将其作为bytes类型包含,然后单独传递“这是什么?”信息(可能是鉴别器/枚举)
    我还应该注意到,一些实现方法可能更多地支持此功能;protobuf-net (C# / .NET)分别支持继承和动态消息类型(即上面所述),但主要用于从一个库到另一个库的使用。由于这一切都是除了规范之外的内容(在线格式方面保持100%有效),因此解释来自其他实现方法的此类数据可能会变得混乱不清。

  • 由于我无法预先知道所有可能的消息,因此我将采用单独的序列化解决方案,使用“bytes”字段,谢谢。 - DeX3

    3

    除了多个 optional 字段之外,自 v2.6 版本的 Protocol Buffers 中可以使用 oneof 关键字。

    message UnionMessage {
      oneof data {
        string a = 1;
        bytes b = 2;
        int32 c = 3;
      }
    }
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接