1

我以为每次我不使用预期的消息类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;
}

哪里TeamStatusErrorEnums

当我执行应该导致 a 的代码时ErrorMessage,它会解析为 aLoginMessage并混淆两个枚举:error字段与status字段。

那么我怎么能区分这两种类型的消息呢?

似乎它使用结构类型进行优化,因此它不传输字段名称或消息类型,但是解决这个问题的实际方法是什么?我不想在中插入ErrorMessageLoginMessage总是返回 a LoginMessage

我考虑将error字段索引设置为其他消息不会使用的数字,例如ErrorMessage error = 15000;,但我不知道这是否正确,也不知道它是否总是有效(想象一下,如果所有字段LoginMessage都是可选的,它会起作用吗?) .

4

1 回答 1

2

No, that won't error. Enums are just integers when serialized, and unexpected values are stored in the extension data - so field 1 is entirely interchangeable between the messages. Since "user" is optional, it won't matter if it isn't there - and if it is there but isn't expected, it will be stored in the extension data.

It seems that it uses structural typing for optimization, so it doesn't transmit field names or message types

That is correct; only field numbers and data are transferred. No names.

The best way to tell messages apart is via some kind of prefix. The easiest way t do this is with a wrapper message:

 message SomeWrapper {
     optional LoginMessage login = 1;
     optional ErrorMessage error = 2;
 }

Then when deserializing, just check which field has a value. Obviously when serialising you'll need to wrap the value in a SomeWrapper, too. Note that optional values that aren't included incur zero cost.

于 2012-10-04T16:30:37.680 回答