我想在每次不使用预期的邮件类时尝试InvalidProtocolBufferException
时会得到parseFrom(bytes)
。
我的代码如下所示:
try {
LoginMessage msg = LoginMessage.parseFrom(bytes);
// ... use msg ...
} catch(InvalidProtocolBufferException exception) {
ErrorMessage error = ErrorMessage.parseFrom(bytes);
// ... do something ...
}
我的信息是这些:
message LoginMessage
{
required Status status = 1;
optional UserMessage user= 2;
}
message ErrorMessage
{
required Error error = 1;
}
其中TeamStatus
和Error
是枚举。
当我执行应该导致ErrorMessage
的代码时,它会解析为LoginMessage
并混淆两个枚举:error
字段和status
字段。
那么我怎么能区分这两种消息?
它似乎使用结构类型进行优化,因此它不传输字段名称或消息类型,但解决此问题的实际方法是什么?我不想在ErrorMessage
中插入LoginMessage
并始终返回LoginMessage
。
我考虑将error
字段索引设置为其他消息不会使用的数字,例如ErrorMessage error = 15000;
,但我不知道这是否正确,也不知道它是否始终有效(想象如果LoginMessage
中的所有字段都是可选的,它会起作用吗?)。
答案 0 :(得分:2)
不,那不会出错。枚举在序列化时只是整数,并且意外值存储在扩展数据中 - 因此字段1在消息之间完全可以互换。由于“user”是可选的,如果它不在那里也无关紧要 - 如果它 但不是预期的,它将存储在扩展数据中。
它似乎使用结构类型进行优化,因此它不传输字段名称或消息类型
这是正确的;传输仅字段编号和数据。没有名字。
分辨信息的最好方法是通过某种前缀。最简单的方法是使用包装器消息:
message SomeWrapper {
optional LoginMessage login = 1;
optional ErrorMessage error = 2;
}
然后在反序列化时,只需检查哪个字段有值。显然,在序列化时,您还需要将值包装在SomeWrapper中。请注意,未包含的可选值会产生零成本。