まくろぐ
更新: / 作成:

フィールド番号の基本

Protocol Buffers の .proto ファイルの型定義では、各フィールドの末尾に フィールド番号 を割り当てておく必要があります。

フィールド番号の割り当て例
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

= 記号が使われていますが、そのフィールドに値を代入しているわけではないので注意してください。 Protocol Buffers は、メッセージ送信用にデータをシリアライズ(バイナリ化)するとき、フィールド名の代わりにこのフィールド番号を使用します。 これにより、Protocol Buffers は効率的なデータ転送を実現しています。

フィールド番号は 1 以上の整数(最大値は 229-1 = 536,870,911)で、メッセージの定義内(同じ階層)で一意になっている必要があります。 必ずしも 1、2、3 のように連番で割り当てる必要はなく、ほぼ任意の数値を割り当てることができますが、19000 ~ 19999 の値は使えません。 これらは、Protocol Buffers ライブラリが内部実装用に予約している値です。 これらの不正な値を使用していると、protoc コマンドなどでコンパイルしようとしたときにエラーになります。

データをシリアライズするとき、フィールド番号 1~15 の数値は、わずか 1 バイトのデータに変換されるため、頻繁に使用するフィールドには 1~15 のフィールド番号を割り当てておくと効率的な通信を行えます。 とはいえ、フィールド番号が 16~2047 であっても、2 バイトのデータで表現できるので、シビアな通信速度が求められている環境でなければそれほど気にする必要はないでしょう。

reserved と deprecated

reserved

一度割り当てたフィールド番号は、将来にわたって変更してはいけません。 なぜなら、過去のバージョンの .proto を使って実装されたアプリケーションは、古い .proto で割り当てられたフィールド番号で通信しようとするためです。 同じフィールド番号で異なるデータが送られてきたら、アプリケーションはうまく動作しなくなってしまいます。 .proto を更新して非推奨になったフィールドを削除するときは、フィールド番号やフィールド名を使いまわしてしまわないように、reserved キーワードを使って次のように定義しておきます。

フィールド番号の予約
enum Foo {
  reserved 2, 5 to 10, 40 to max;
  reserved "FOO_AAA", "FOO_BBB"
  // ...
}

この例では、25~1040~最大値 のフィールド番号の使用と、FOO_AAAFOO_BBB というフィールド名(この例の場合は列挙値)の使用を制限しています。 1 つの reserved 行では、数値のリストあるいは文字列のリストのどちらかしか定義できないので、上記のように 2 行に分けて定義する必要があります。 reserved キーワードは、その名前が示しているように、将来的にこれらのフィールド番号を使うために「予約」しておく、という用途でも使用できます。

deprecated

フィールドオプション (field option) の機能を使って、既存のフィールドに deprecated(非推奨)の印を付けることができます。

int32 old_field = 6 [deprecated = true];

このオプションが付いたフィールドを、Java や Kotlin のコードとして出力すると、@Deprecated アノテーションとして出力されますが、言語によっては何も効果がないことがあります。 ただ、ドキュメンテーションコメントとしては役に立つので活用するとよいです。

関連記事

まくろぐ
サイトマップまくへのメッセージ