在java端我可以反序列化流,以便我可以找出流中有3个字段及其各自的name
, type
, 和value
您需要提前了解架构。首先,protobuf不传输名称;它用作标识符的只是每个字段的数字键(1
,在您2
的3
示例中)。其次,它没有明确指定类型;protobuf 中只有很少的线类型(varint、32 位、64 位、长度前缀、组);实际的数据类型映射到那些,但你不能在没有模式的情况下明确解码数据
- varint 是“某种形式的整数”,但可以是有符号、无符号或“之字形”(允许对小幅度负数进行廉价编码),并且可以用于表示任何宽度的数据(64 位、32 位、 ETC)
- 32 位可以是整数,但可以是有符号或无符号的 - 也可以是 32 位浮点数
- 64 位可以是整数,但可以是有符号或无符号的 - 也可以是 64 位浮点数
- 长度前缀可以是 UTF-8 字符串、序列或原始字节(没有任何特殊含义)、
repeated
某些原始类型(整数、浮点等)的“打包”值集,或者可以是结构化子protobuf 格式的消息
- 团体 - 万岁!这始终是明确的!这只能意味着一件事;但是一件事在很大程度上被谷歌弃用了:(
所以从根本上说:你需要模式。编码数据不包括您想要的。这样做是为了避免不必要的空间——如果协议假设编码器和解码器都知道消息的含义,那么需要发送的信息就会少得多。
但是请注意,即使存在不期望的字段,所包含的信息也足以安全地往返消息;如果您只需要重新编码以将其传递/返回,则无需知道名称或类型。
您可以做的是使用解析器 API 扫描数据以显示有三个字段,字段 1 是 varint,字段 2 是长度前缀,字段 3 是长度前缀。您可以对除此之外的数据进行有根据的猜测(例如,您可以查看 UTF-8 解码是否产生看起来大致类似于文本的内容,并验证 UTF-8 编码是否会返回原始字节;如果确实如此,它可能是一个字符串)