我试图升级到使用Proto3版本,并与版本2保持向后兼容。除了一件事--在proto-2中,您可以设置自己的默认值,但在proto 3中,您不能。如果您选择了proto-2中的默认值,而这不是proto-3中的标准默认值,那么您就有问题了。例如,在原语2中:
message Record {
required uint32 fileno = 1;
required uint64 pos = 2;
optional uint64 bmsPos = 3 [default = 0];
optional uint32 scanMode = 4 [default = 9999];
}
现在第三原语必须是:
message Record {
uint32 fileno = 1;
uint64 pos = 2;
uint64 bmsPos = 3;
uint32 scanMode = 4;
}
在proto-2和proto-3中,没有在消息中发送缺少的值。但是Proto-3API并不告诉您默认值是否在消息中,它只是告诉您这个值。
所以proto-3接收器收到一条消息,并告诉我scanMode = 0
.如果该消息来自原-2发送方,则原语-2发送方在消息中放置0,或者2)原-2发送方将值设置为9999 (默认值),因此不发送该值,而proto-3接收方将其解释为0。在不知道消息中是否存在值的情况下,我的代码无法消除歧义,即使它知道消息是来自proto-2还是proto-3发送方。
请注意,示例中的bmsPos
字段没有问题,因为proto-2消息使用与proto-3 (0)相同的默认值。但是,如果您碰巧选择了一个与proto-3不同的默认值,那么我就不知道如何升级到proto-3并向后兼容。
发布于 2015-10-18 23:40:42
事实证明,有一种方法可以找出默认值是否真的丢失(感谢google的一些朋友提供了这个答案):
message Record {
uint32 fileno = 1;
uint64 pos = 2;
uint64 bmsPos = 3;
oneof scanMode_present {
uint32 scanMode = 4;
}
uint32 version = 5; // set to >= 3 for protobuf 3
}
使用getXXXcase()方法,生成代码有其他方法来检测是否设置了一个字段:
int scanMode = proto.getScanMode();
boolean isMissing = proto.getScanModePresentCase() == Record.ScanModePresentCase.SCANMODEPRESENT_NOT_SET;
if (isMissing) {
boolean isProto3 = proto.getVersion() >= 3;
scanMode = (isProto3) ? 0 : 9999;
}
有了这个“技巧”,我已经升级到原-3与非标准的原-2默认值向后兼容。
https://stackoverflow.com/questions/33204321
复制相似问题