2

我是协议缓冲区的新手,真的很想知道更多关于它的信息,很抱歉这个菜鸟问题。

序列化数据中的内容是什么,只有值还是键和值?我认为只有价值观,如果有人想反序列化它,他/她必须有计划。

4

2 回答 2

3

它既是关键又是价值:

如您所知,协议缓冲区消息是一系列键值对。消息的二进制版本只是使用字段的编号作为键——每个字段的名称和声明的类型只能在解码端通过引用消息类型的定义(即 .proto 文件)来确定。 https://developers.google.com/protocol-buffers/docs/encoding

例如,假设您有一个 proto 文件:

$  cat my.proto 
message header {
  required uint32 u1 = 1;
  required uint32 u2 = 2;
  optional uint32 u3 = 3 [default=0];
  optional bool   b1 = 4 [default=true];
  optional string s1 = 5;
  optional uint32 u4 = 6;
  optional uint32 u5 = 7;
  optional string s2 = 9;
  optional string s3   = 10; 
  optional uint32 u6 = 8;
}

从内存中转储编码数据:

(gdb) x/10xb 0x7fd70db7e964
0x7fd70db7e964: 0x08    0xff    0xff    0x01    0x10    0x08    0x40    0xf7
0x7fd70db7e96c: 0xd4    0x38

解码:

$ echo 08ffff01100840f7d438 | xxd -r -p | protoc --decode_raw
1: 32767
2: 8
8: 928375

1,2,8 是键

从上面的原始文件:

1 => u1, 
2 => u2,
8 => u6

所以,它变成:

u1: 32767
u2: 8
u6: 928375

我在这里使用了我的问题中的数据:

于 2018-12-06T17:04:30.010 回答
2

这在一定程度上取决于您是使用二进制形式(这通常是处理 protobuf 时的默认形式)还是 json 形式(是的,protobuf 包含 json 选项,至少在某些库中 - 不是全部)。

在二进制形式中,数据由字段编号和值组成;不是字段名称。例如,如果我们使用以下示例:

optional string name = 1; // remove the "optional" if using proto3 syntax

并分配一个值“Nika”(并对其进行序列化),然后二进制数据将包括1(以稍微调整的形式)和 UTF-8 编码形式Nika,但它不会包含“名称”。

你不一定需要有模式来解码它,但如果你这样做会使事情变得容易,因为规范的许多部分在其他方面都是模棱两可的,使用相同的“线类型”(即编码格式)多种数据类型,或同一数据类型的多种含义(例如:如果没有模式(或很好的猜测)和实际值,您无法判断整数是有符号、无符号还是“之字形编码”基于此,您得到的结果可能会有很大差异。

要查看在没有架构的情况下您可以从原始 protobuf 数据中获得什么,请尝试:https ://protogen.marcgravell.com/decode

于 2018-12-06T17:03:58.493 回答