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;
}

ここでTeamStatus、およびError列挙型です。

結果が。になるはずのコードを実行するErrorMessageと、aに解析され、LoginMessage両方の列挙型:errorfieldとstatusfieldが混同されます。

では、これら2つのタイプのメッセージをどのように区別できますか?

最適化に構造型を使用しているようですので、フィールド名やメッセージタイプは送信しませんが、この問題を解決する実際的な方法は何でしょうか。ErrorMessageにを挿入したくないのでLoginMessage、常にを返しますLoginMessage

errorフィールドインデックスを他のメッセージが使用しない数値に設定することを考えましたErrorMessage error = 15000;が、これが正しいかどうか、また常に機能するかどうかはわかりません(のすべてのフィールドLoginMessageがオプションであるとしたら、機能するでしょうか?) 。

4

1 に答える 1

2

いいえ、エラーにはなりません。列挙型はシリアル化された場合は単なる整数であり、予期しない値が拡張データに格納されるため、フィールド1はメッセージ間で完全に交換可能です。「user」はオプションであるため、存在しないかどうかは関係ありません存在するが予期されていない場合は、拡張データに保存されます。

最適化に構造型を使用しているようですので、フィールド名やメッセージタイプは送信しません

それは正しいです; フィールド番号とデータのみが転送されます。名前はありません。

メッセージを区別する最良の方法は、ある種のプレフィックスを使用することです。これを行う最も簡単な方法は、ラッパーメッセージを使用することです。

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

次に、逆シリアル化するときに、どのフィールドに値があるかを確認するだけです。明らかに、シリアル化するときは、値をSomeWrapperでラップする必要もあります。含まれていないオプションの値はゼロコストになることに注意してください。

于 2012-10-04T16:30:37.680 に答える