Omr*_*eor 5 protocol-buffers python-3.x
我有以下消息:
message Message {
int64 id = 1;
google.protobuf.FloatValue weight = 2;
google.protobuf.FloatValue override_weight = 3;
}
Run Code Online (Sandbox Code Playgroud)
我希望更改权重和 override_weight(可选字段)的类型,google.protobuf.DoubleValue以便我所做的是以下内容:
message Message {
int64 id = 1;
oneof weight_oneof {
google.protobuf.FloatValue weight = 2 [deprecated=true];
google.protobuf.DoubleValue double_weight = 4;
}
oneof override_weight_oneof {
google.protobuf.FloatValue override_weight = 3 [deprecated=true];
google.protobuf.DoubleValue double_override_weight = 5;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,假设我有旧消息,这些消息是由以前的 protobuff 消息编译器为旧消息编译的,我是否能够将它们解析为新消息?该文档对此非常模糊:
“将可选字段移入或移出 oneof:在消息被序列化和解析后,您可能会丢失一些信息(某些字段将被清除)。但是,您可以安全地将单个字段移入新的 oneof,并且可能能够如果已知只设置了一个字段,则移动多个字段。”
以前有人尝试过这个吗?这种情况的最佳做法是什么?
据我所知,oneof 中的字段只是使用其标签号进行序列化。序列化数据并不指示字段是否是 oneof 的一部分。这全部由串行器和解串器处理。因此,只要标签号不冲突,就可以假设它将在两个方向上工作,即旧消息发送到新序列化器,新消息发送到旧序列化器。
您可以使用在线 protobuf 反序列化器对此进行测试。
验证:代码确实产生了相同的字节字符串。下面你将找到我使用的消息定义和 python 代码。python 代码将输出一个字节字符串,您可以在 Marc Gravell 的解码器中复制和使用。
syntax = "proto3";
message MessageA {
int64 id = 1;
float weight = 2;
float override_weight = 3;
}
message MessageB {
int64 id = 1;
oneof weight_oneof {
float weight = 2 [deprecated=true];
double double_weight = 4;
}
oneof override_weight_oneof {
float override_weight = 3 [deprecated=true];
double double_override_weight = 5;
}
}
Run Code Online (Sandbox Code Playgroud)
import Example_pb2
# Set some data in the original message
msgA = Example_pb2.MessageA()
msgA.id = 1234
msgA.weight = 3.21
msgA.override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgA = '
for x in msgA.SerializeToString():
str += "{:02x} ".format(x)
print(str)
# Next set the original fields in the new message
msgB = Example_pb2.MessageB()
msgB.id = 1234
msgB.weight = 3.21
msgB.override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgB 1 = '
for x in msgB.SerializeToString():
str += "{:02x} ".format(x)
print(str)
# And finally set the new fields in msgB
msgB.double_weight = 3.21
msgB.double_override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgB 2 = '
for x in msgB.SerializeToString():
str += "{:02x} ".format(x)
print(str)
Run Code Online (Sandbox Code Playgroud)
python 脚本的输出是:
msgA = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 1 = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 2 = 08 d2 09 21 ae 47 e1 7a 14 ae 09 40 29 b8 1e 85 eb 51 b8 15 40
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,在设置原始字段时,消息 A 和消息 B 产生相同的字节字符串。仅当您设置新字段时,您才会得到不同的字符串。