2017-03-06 4 views
8

protobuf(proto3構文)にオプションのフィールドを持つメッセージを指定する必要があります。プロト2構文の面では、私が表現したいメッセージのようなものです:私の理解からprotobufでオプションフィールドを定義する方法3

message Foo { 
    required int32 bar = 1; 
    optional int32 baz = 2; 
} 

「オプション」のコンセプトは、(必要な概念と一緒に)構文プロト3から削除されました。代わりに、デフォルト値を使用してフィールドが送信者から指定されていないことを示す代替方法が明確ではありませんが、デフォルト値が有効な値のドメインに属している場合はあいまいなままです(ブール型など)。

私は上記のメッセージをどのようにエンコードする必要がありますか?ありがとうございました。

+0

は、サウンドソリューション以下のアプローチですか? メッセージNoBaz { } メッセージFoo { int32 bar = 1; baz { NoBaz undefined = 2; int32 defined = 3; }; } – MaxP

答えて

17

proto3では、すべてのフィールドは「オプション」です(送信者が設定できなかった場合はエラーではありません)。しかし、フィールドは明示的にデフォルト値に設定されているフィールドと設定されていないフィールドの違いを伝える方法がないため、もはや "nullable"ではありません。

"null"状態が必要な場合(範囲外の値は使用できません)、代わりにこれを別のフィールドとしてエンコードする必要があります。たとえば、あなたが行うことができます:

message Foo { 
    bool has_baz = 1; 
    int32 baz = 2; 
} 

また、あなたがoneofを使用することができます。

message Foo { 
    oneof baz { 
    bool baz_null = 1; // always set this to "true" when using 
    int32 baz_value = 2; 
    } 
} 

oneofバージョンは、ワイヤ上のより明確かつより効率的ですが、oneof値がどのように働くか理解する必要があり。

最後に、もう1つの完全に合理的な選択肢は、proto2を使用することです。 Proto2は廃止予定ではなく、実際には(Googleを含む)多くのプロジェクトはproto3で削除されたproto2の機能に非常に依存しているため、決して切り替えることはありません。それで、それを近い将来使用し続けることは安全です。

+0

あなたのソリューションに似て、私のコメントでは、私は実際の値とnull型(空のメッセージ)のoneofを使用することを提案しました。この方法でブール値を気にする必要はありません(ブール値がある場合はbaz_valueがないので、関係しないはずです)。 – MaxP

+2

@MaxPあなたの解決策は動作しますが、空のメッセージに対してブール値を使うことをお勧めします。ワイヤー上で2バイトを取るが、空のメッセージは処理するためにかなり多くのCPU、RAM、および生成コードが膨らんでしまう。 –

+2

私はメッセージFooを見つけます{ baz { int32 baz_value = 1; } }はうまく機能します。 – CyberSnoopy

0

ケントンの回答に基づいて、単純まだ作業溶液は次のようになります。

message Foo { 
    oneof optional_baz { // "optional_" prefix here just serves as an indicator, not keyword in proto2 
     int32 baz = 1; 
    } 
} 
関連する問題