在不知道消息类型的情况下解组原始编码消息
Unmarshaling a proto encoded message without knowing what type it is
我想把一个 []byte
变成一个 proto.Message 而事先不知道它是什么类型。
要添加更多细节,我知道编码 type/message 可以是的类型的集合 S。 (它们都是在我自己的 proto 文件中声明并内置到 Go 二进制文件中的类型。)
我想看看是否可以获取字节数组并从中重建原始消息。
我写了这个演示:https://play.golang.org/p/WF9KpTlZnp7
如果我将描述符传递给它,我可以将它解码为 dynamicpb,并从 Any 返回消息。
Protocol Buffers 有线格式不是自描述的。这意味着有关协议缓冲区类型的信息未与消息本身一起编码。这就是为什么在解组期间必须提供类型。
在线上,protobuf格式真的很简单。基本上只有字段编号(注意不是名称,只有数字)和值(序列化为字节)被编码。
有两种动态解码消息的策略。
一个正在使用 Any
。
https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto
对于能够使用 any 包解码的消息,必须首先使用 any 包对其进行编码,并且必须在解码和编码原型注册表中注册该类型。这是因为,any 是通过简单地对底层消息进行编码然后将其放入带有引用该类型的字符串的消息中来实现的。通常这被称为信封,因为就像一封信,原始消息被这个额外的上下文(消息的类型)包裹着。
如果您可以同时控制编码和解码代码,则此策略效果最佳。如果可能的话,这将是推荐的策略。
另一种策略是使用 dynamicpb
并尝试解析未知字段。这是可行的,因为从 proto 3.5 开始,添加了未知字段。如果原始消息被反序列化,但原始类型不知道该字段,则其余字段将被推入未知字段。消息类型中不传递类型信息和字段名称。因此这些字段将显示为具有未知名称和类型的未知字段。
如果您的消息不同,但是,例如,共享一个具有相同编号和类型的描述类型的字段,这可用于首先反序列化该字段,然后在打开第一个字段中已知的信息。
这更多是针对不控制编码路径的系统的变通方法,不是推荐的策略。
我想把一个 []byte
变成一个 proto.Message 而事先不知道它是什么类型。
要添加更多细节,我知道编码 type/message 可以是的类型的集合 S。 (它们都是在我自己的 proto 文件中声明并内置到 Go 二进制文件中的类型。)
我想看看是否可以获取字节数组并从中重建原始消息。
我写了这个演示:https://play.golang.org/p/WF9KpTlZnp7 如果我将描述符传递给它,我可以将它解码为 dynamicpb,并从 Any 返回消息。
Protocol Buffers 有线格式不是自描述的。这意味着有关协议缓冲区类型的信息未与消息本身一起编码。这就是为什么在解组期间必须提供类型。
在线上,protobuf格式真的很简单。基本上只有字段编号(注意不是名称,只有数字)和值(序列化为字节)被编码。
有两种动态解码消息的策略。
一个正在使用 Any
。
https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto
对于能够使用 any 包解码的消息,必须首先使用 any 包对其进行编码,并且必须在解码和编码原型注册表中注册该类型。这是因为,any 是通过简单地对底层消息进行编码然后将其放入带有引用该类型的字符串的消息中来实现的。通常这被称为信封,因为就像一封信,原始消息被这个额外的上下文(消息的类型)包裹着。
如果您可以同时控制编码和解码代码,则此策略效果最佳。如果可能的话,这将是推荐的策略。
另一种策略是使用 dynamicpb
并尝试解析未知字段。这是可行的,因为从 proto 3.5 开始,添加了未知字段。如果原始消息被反序列化,但原始类型不知道该字段,则其余字段将被推入未知字段。消息类型中不传递类型信息和字段名称。因此这些字段将显示为具有未知名称和类型的未知字段。
如果您的消息不同,但是,例如,共享一个具有相同编号和类型的描述类型的字段,这可用于首先反序列化该字段,然后在打开第一个字段中已知的信息。
这更多是针对不控制编码路径的系统的变通方法,不是推荐的策略。