Proto3 Language Guide（和訳）


# これはなに

Protocol Buffers バージョン３の Language Guide の訳がありそうで見つからなかったので訳した．

原文：https://developers.google.com/protocol-buffers/docs/proto3

Portions of this page are modifications based on work created and [shared by Google](https://developers.google.com/readme/policies/) and used according to terms described in the [Creative Commons 3.0 Attribution License](http://creativecommons.org/licenses/by/3.0/) and [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0) for code samples.

# Language Guide (proto3)

このガイドは，プロトコルバッファーデータを組み立てるために，どのようにプロトコルバッファー言語を使用するかについて述べる．ガイドには，`.proto` ファイルのシンタックスについてと，`.proto` ファイルからデータアクセスクラスをどのように生成するかについての記述を含む．このガイドは **proto3** バージョンについてカバーしている．古い **proto2** バージョンについては，[Proto2 Language Guide](https://developers.google.com/protocol-buffers/docs/proto) を参照されたい．

これはレファレンス・ガイドである――このドキュメントで述べられているたくさんの特徴を用いたステップ・バイ・ステップの例については，言語別の [tutorial](https://developers.google.com/protocol-buffers/docs/tutorials) を参照されたい（現在は proto2 のみである；より多くの proto3 ドキュメンテーションについては近日公開）．

# メッセージタイプを定義する

はじめにとても簡単な例を見てみよう．検索リクエストメッセージフォーマットを定義したいとする．各検索リクエストはクエリ文字列，興味のあるページの番号，１ページあたりの結果の数を含む．これがこのメッセージタイプを定義する `.proto` ファイルである．

```protobuf
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
```

- ファイルの最初の行では `proto3` のシンタックスを用いていることを明記している．これを記述しないと，プロトコルバッファーのコンパイラは `proto2` を用いていると考える．この記述は，空でなくコメント行でないファイルの最初の行になければならない．

- `SearchRequest` メッセージ定義は，このメッセージ型の中に含めたいデータに対する３つのフィールドを明記している（名前 / 値のペア）．各フィールドは名前と型を持つ．

## フィールドの型指定

上記の例に於いて，全てのフィールドは[スカラー型](#scalar)である．即ち，２つの整数 (`page_number`, `result_per_page`)と文字列 (`query`) である．フィールドには，[列挙型](#enum)や他のメッセージ型などの複合型を指定することもできる．

## タグの割り当て

既に見たように，メッセージ定義の各フィールドはユニークな数値タグを持つ．これらのタグは[メッセージのバイナリフォーマット](https://developers.google.com/protocol-buffers/docs/encoding)に於いてフィールドを区別するために使われる．一度あなたのメッセージ型が使われたら，もはやタグを変えるべきではない．留意すべきことだが，1 から 15 までのタグは，数値とフィールドの型を含めて 1 バイトでエンコードされる（[Protocol Buffer Encoding](https://developers.google.com/protocol-buffers/docs/encoding#structure) に詳しい）．16 から 2047 までのタグは 2 バイト用いる．よって，非常によく使われるメッセージ要素のために 1 から 15 までのタグは取っておくべきである．将来加えられるかもしれない非常によく使われる要素のために，ある程度の余地を残すということを覚えておけ．

指定できる最小のタグ値は 1 で，最大は 2<sup>29</sup>-1, 即ち 536,870,911 である．また，19000 から 19999 まで（`FieldDescriptor::kFirstReservedNumber` から `FieldDescriptor::kLastReservedNumber` まで）の数値は使ってはいけない．これはプロトコルバッファーの実装によって予約されている．もし `.proto` ファイル内でこの数値を使った場合，プロトコルバッファーコンパイラは文句を垂れるだろう．同様に，前もって[予約](#reserved)されたタグは使ってはならない．

## フィールド規則指定

メッセージフィールドは以下のいずれかになれる．

- singular: 正しい形式のメッセージは，このフィールドについて 0 つか 1 つの値を持つことができる (1 つより多くは持てない)．

- `repeated`: 正しい形式のメッセージに於いて，このフィールドは何回でも繰り返されうる（0 回を含む）．繰り返される値の順番は保存される．

proto3 では，スカラー数値型の `repeated` フィールドはデフォルトで `packed` エンコーディングを用いる．

`packed` エンコーディングについては [Protocol Buffer Encoding](https://developers.google.com/protocol-buffers/docs/encoding#packed) に詳しい．

## 他のメッセージ型を追加する

1 つの `.proto` ファイル内には複数のメッセージ型が定義されうる．複数の関係したメッセージを定義したい時には便利だ――例えば，あなたの `SearchResponse` メッセージ型に対する返信メッセージのフォーマットを定義したいならば，同じ `.proto` ファイルに加えることができる．

```protobuf
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
 ...
}
```

## コメント

コメントを加えたいならば，C/C++ スタイルの `//` シンタックスを用いるがよい．

```protobuf
message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}
```

## 予約フィールド <a name="reserved"></a>

もしあるフィールドを完全に取り除いたりコメントアウトしてメッセージ型を更新した場合，未来のユーザはその型に対して独自の更新を行うとき，そのタグ番号を再使用するかもしれない．彼らが同じ `.proto` の古いバージョンを読み込んだ時，問題が発生する．データの破損，プライバシーについてのバグ，などなど．このようなことが起きないようにする一つの方法は，削除したフィールドのタグ（もしくはフィールド名，例えば JSON のシリアライズ周りでの問題がある）が `reserved` であると明記しておくことだ．未来のユーザがそれらのフィールド識別子を使おうとすると，プロトコルバッファーコンパイラは文句を垂れるだろう．

```protobuf
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
```

同じ `reserved` ステートメント内にフィールド名とタグ番号を混ぜることはできないことに留意されたい．

## `.proto` ファイルから何が生成されるか？

`.proto` ファイルをプロトコルバッファーコンパイラにかけると，コンパイラはあなたの選択した言語のコードを生成する．生成されるコードには，定義したメッセージ型や，フィールドのゲッター / セッター，出力のためのシリアライズ，入力されたデータのパースなどが含まれる．

- **C++** では，コンパイラは各 `.proto` に対して `.h` と `.cc` ファイルを生成する．ファイルには定義された各メッセージ型に対するクラスが含まれる．

- **Java** では，コンパイラは各メッセージ型に対するクラスや，クラスインスタンスを生成するための `Builder` クラスを含んだ `.java` ファイルを生成する．

- **Python** は少々異なる――Python コンパイラは `.proto` 内の各メッセージ型の静的デスクリプタを含んだモジュールを生成する．それは必要な Python データアクセスクラスをランタイムに生成するためのメタクラスと共に用いられる．

- **Go** では，コンパイラは各メッセージ型に対する型を含んだ `.pb.go` ファイルを生成する．

- **Ruby** では，コンパイラはメッセージ型を含んだ Ruby モジュールを持つ `.rb` ファイルを生成する．

- **JavaNano** では，コンパイラの出力は Java に似ているが，`Builder` クラスがない．

- **Objective-C** では，コンパイラは各 `.proto` ファイルに対して `pbobjc.h` と `pbobjc.m` ファイルを生成する．生成されたファイルには定義された各メッセージ型が含まれる．

- **C#** では，コンパイラは各 `.proto` ファイルに対して，定義されたメッセージ型を含んだ `.cs` ファイルを生成する．

各言語についてのチュートリアルを追うことで，それぞれの言語での API の使い方についてより学ぶことができるだろう（proto3 バージョンは近日公開）．API の詳細については [API Reference](https://developers.google.com/protocol-buffers/docs/reference/overview) を参照されたい（proto3 バージョンについてはもう少し待て）．

# スカラー値型 <a name="scalar"></a>

スカラーメッセージフィールドは以下の型の１つを持つ．以下の表は `.proto` ファイルで指定される型と，対応する自動生成クラス内での型を示す．

| .proto Type | Notes | C++ Type | Java Type | Python Type<sup>[2]</sup> | Go Type | Ruby Type | C# Type | PHP Type |
|:--|:--|:--|:--|:--|:--|:--|:--|:--|
| double | | double | double | float | float64 | Float | double | float |
| float | | float | float | float | float32 | Float | float | float |
| int32 | 可変長エンコーディング．負数に対して非効率．負数を持つ虞がある場合は sint32 を用いよ． | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer　|
| int64 | 可変長エンコーディング．負数に対して非効率．負数を持つ虞がある場合は sint64 を用いよ． | int64 | long | int/long<sup>[3]</sup> | int64 | Bignum | long | integer/string<sup>[5]</sup> |
| uint32 | 可変長エンコーディング | uint32 | int<sup>[1]</sup> | int/long<sup>[3]</sup> | uint32 | Fixnum or Bignum (as required) | uint | integer |
| uint64 | 可変長エンコーディング | uint64 | long<sup>[1]</sup> | int/long<sup>[3]</sup> | uint64 | Bignum | ulong | integer/string<sup>[5]</sup> |
| sint32 | 可変長エンコーディング．符号付き int．int32 より負数に対して高効率． | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer |
| sint64 | 可変長エンコーディング．符号付き int．int64 より負数に対して高効率． | int64 | long | int/long<sup>[3]</sup> | int64 | Bignum | long | integer/string<sup>[5]</sup> |
| fixed32 | 常に 4 バイト．値が屡々 2<sup>28</sup> を超える場合，uint32 より高効率． | uint32 | int<sup>[1]</sup> | int | uint32 | Fixnum or Bignum (as required) | uint | integer |
| fixed64 | 常に 8 バイト．値が屡々 2<sup>56</sup> を超える場合，uint64 より高効率． | uint64 | long<sup>[1]</sup> | int/long<sup>[3]</sup> | uint64 | Bignum | ulong | integer/string<sup>[5]</sup> |
| sfixed32 | 常に 4 バイト | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer |
| sfixed64 | 常に 8 バイト | int64 | long | int/long<sup>[3]</sup> | int64 | Bignum | long | integer/string<sup>[5]</sup> |
| bool || bool | boolean | bool | bool | TrueClass/FalseClass | bool | boolean |
| string | UTF-8 エンコードされた，もしくは 7 ビット ASCII テキストでなければならない． | string | String | str/unicode<sup>[4]</sup> | string | String (UTF-8) | string | string |
| bytes | 任意のバイト列 | string | ByteString | str | []byte | String (ASCII-8BIT) | ByteString | string |

メッセージのシリアライズ時にこれらの型がどのようにエンコードされるかについては [Protocol Buffer Encoding](https://developers.google.com/protocol-buffers/docs/encoding) に詳しい．

[1] Java でに於いて，符号なし 32 ビット及び 64 ビット整数は，最上位ビットを単に符号ビットに格納することによって，符号付き整数として表される．

[2] 全ての場合に於いて，フィールドへ値を設定する時に型チェックが行われる．

[3] 64 ビットもしくは符号なし 32 ビット整数は，デコード時常に long として表される．しかしフィールドに値を設定する際にある int が与えられた場合は int になりうる．その値はセット時，表されている型に一致しなければならない．[2] も見よ．

[4] Python 文字列はデコード時 unicode として表される．しかし ASCII 文字列が与えられた場合は str になりうる（この挙動は変更される可能性がある）．

[5] 64 ビットマシンでは Integer, 32 ビットマシンでは string が用いられる．

# デフォルト値 <a name="default"></a>

メッセージがパースされる時，エンコードされたメッセージがある特定の singular 要素を含んでいなければ，対応するフィールドはそのフィールドのデフォルト値にセットされる．これらのデフォルト値は型により異なる．

- string ではデフォルト値は空文字列である．

- bytes ではデフォルト値は空バイト列である．

- bool ではデフォルト値は false である．

- 数値型ではデフォルト値はゼロである．

- 列挙型 ([enum](#enum)) ではデフォルト値は**最初に定義されている列挙値**であり，これは 0 でなければならない．

- メッセージフィールドでは，フィールドはセットされない．実際の値は言語依存である．詳細は [generated code guide](https://developers.google.com/protocol-buffers/docs/reference/overview) を参照されたい．

repeated フィールドに対するデフォルト値は空（一般に妥当な言語では空リスト）である．

スカラー値のフィールドについては，一度メッセージがパースされたが最後，フィールドが明示的にデフォルト値にセットされたのか，それともセットされなかったのかについて伝える方法はないということに留意されたい（例えば，boolean が `false` にセットされたかどうか）．メッセージ型を定義するときにはこのことを心に留めておくべきである．例えば，もしデフォルトでそのような振る舞いを起こしたくないのであれば，`false` にセットされたときにある振る舞いを変更するような boolean を持つべきではない．また，あるスカラー値のフィールドがそのデフォルト値にセット**された**とき，その値はワイヤ上でシリアライズされないことにも注意すべきである．

デフォルトが生成されたコードにおいてどう機能するのかについての詳細は [generated code guide](https://developers.google.com/protocol-buffers/docs/reference/overview) を参照されたい．

# 列挙型 <a name="enum"></a>

メッセージ型を定義するとき，そのフィールドの一つを，ある事前に定義された値のリストのうちの一つの値を持つようにしたいかもしれない．例えば，各 `SearchRequest` に対して `corpus` フィールドを追加したいとする．`corpus` は `UNIVERSAL`, `WEB`, `IMAGES`, `LOCAL`, `NEWS`, `PRODUCT`, `VIDEO` のいずれかの値になるとする．これは単にメッセージ定義の中に，各値について定数値を持つ `enum` を追加すれば良い．

以下の例では `Corpus` という `enum` と，`Corpus` 型のフィールドを追加した．

```protobuf
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  Corpus corpus = 4;
}
```

`Corpus` enum の最初の定数は 0 にマップされている．全ての enum 定義は**必ず**最初の要素として 0 へマップされた定数を持たなければならない．これは次の理由による．

- 必ずゼロ値が存在することになるため，数値の[デフォルト値](#default)として 0 を用いることができる．

- ゼロ値は最初の要素である必要がある，これは enum の最初の値が常にデフォルトであった [proto2](https://developers.google.com/protocol-buffers/docs/proto) セマンティクスとの互換性のためである．

異なる enum 定数について同じ値を割り当てることでエイリアスを定義することができる．これをするためには `allow_alias` オプションを `true` にする必要がある．さもなくばコンパイラはエラーメッセージを出力するだろう．

```protobuf
enum EnumAllowingAlias {
  option allow_alias = true;
  UNKNOWN = 0;
  STARTED = 1;
  RUNNING = 1;
}
enum EnumNotAllowingAlias {
  UNKNOWN = 0;
  STARTED = 1;
  // RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
}
```

列挙子定数の値は 32 ビット整数の範囲内でなければならない．`enum` 値はワイヤ上で [variant encoding](https://developers.google.com/protocol-buffers/docs/encoding) を用いているため，負数は非効率でありお勧めしない．上のようにメッセージ定義の中で `enum` を定義することもできるし，外でも良い――それらの `enum` は `.proto` ファイル中の他のメッセージ定義で再使用されるだろう．また，異なるメッセージの中にある `enum` 型を他のメッセージの中でフィールドの型として用いることができる．これには `MessageType.EnumType` のようなシンタックスを用いる．

`enum` を用いている `.proto` ファイルをプロトコルバッファーコンパイラにかける時，生成されるコードには Java や C++ では対応する `enum` が，Python では特別な `EnumDescriptor` クラスが含まれるだろう．`EnumDescriptor` クラスは，ランタイムに生成されたクラス中で整数値を持った記号定数のセットを生成するために使われる．

デシリアライズ中，認識されない enum 値はメッセージ中で保持されるが，メッセージがデシリアライズされた時にどのように表されるかは言語依存である．C++ や Go のような，値が特定のシンボルの範囲外にあるオープン列挙型をサポートしている言語では，不明な enum 値は単にその下層にある整数表現として格納される．Java のようなクローズド列挙型の言語では，enum 中のケースが不正な値を表現するために使われ，下層の整数には特別なアクセサによりアクセスできる．何れの場合においても，メッセージがシリアライズされるときは，認識されない値もメッセージと一緒にシリアライズされる．

アプリケーション中で `enum` とメッセージがどのように機能するかについての詳細は [generated code guide](https://developers.google.com/protocol-buffers/docs/reference/overview) を参照されたい．

# 他のメッセージ型を使う

他のメッセージ型をフィールドの型として使うことができる．例えば，各 `SearchResponse` メッセージ中に `Result` メッセージを含めたいとする――このために，同じ `.proto` ファイル内で `Result` メッセージ型を定義し，`SearchResponse` 内でフィールドの型を `Result` に指定することができる．

```protobuf
message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}
```

## 定義のインポート

上記の例では，`Result` メッセージ型は `SearchResponse` と同じファイルで定義されている――フィールドの型として使いたいメッセージ型が，既に他の `.proto` ファイルで定義されている場合はどうだろう？

他の `.proto` ファイルでの定義は，それらをインポートすることで使うことができる．他の `.proto` の定義をインポートするには，ファイルの先頭にインポート文を加える．

```protobuf
import "myproject/other_protos.proto";
```

デフォルトでは直接インポートされた `.proto` ファイルの定義のみ使うことができる．しかし，時に `.proto` ファイルを新しい場所へ移動したいこともあるだろう．`.proto` ファイルを直接動かして一挙に全ての呼び出し元を更新する代わりに，古い場所にダミーの `.proto` ファイルを置いて，新しい場所へフォワーディングすることができる．これには `import public` の概念を用いる．`import public` の依存性は，`import public` 文を含んだ proto ファイルをインポートする人に依拠し推移する．例えば：

```protobuf
// new.proto
// All definitions are moved here
```

```protobuf
// old.proto
// This is the proto that all clients are importing.
import public "new.proto";
import "other.proto";
```

```protobuf
// client.proto
import "old.proto";
// You use definitions from old.proto and new.proto, but not other.proto
```

プロトコルコンパイラは `-I` / `--proto_path` コマンドラインフラグによって指定されたディレクトリの中で，インポートされているファイルを検索する．もし何のフラグも与えられなければ，コンパイラが呼ばれたディレクトリの中で検索する．一般には `--proto_path` フラグをプロジェクトルートにセットして，全てのインポートについて完全修飾名を用いるべきである．

## proto2 のメッセージ型を用いる

proto2 のメッセージ型をインポートして proto3 のメッセージ中で使うこと，もしくはその逆も可能である．しかしながら，proto2 の enum は proto3 のシンタックスでは直接は使えない（インポートされた proto2 メッセージがそれらを使っている分には ok である）．

# 入れ子型

他のメッセージ型の中でメッセージタイプを定義したり使ったりすることができる．次の例では，`SearchResponse` メッセージ中で `Result` メッセージが定義されている．

```protobuf
message SearchResponse {
  message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
  }
  repeated Result results = 1;
}
```

もしその親のメッセージ型の外でメッセージ型を再使用したい場合は，`Parent.Type` のようにして参照する：

```protobuf
message SomeOtherMessage {
  SearchResponse.Result result = 1;
}
```

メッセージは好きなだけネストできる．

```protobuf
message Outer {                  // Level 0
  message MiddleAA {  // Level 1
    message Inner {   // Level 2
      int64 ival = 1;
      bool  booly = 2;
    }
  }
  message MiddleBB {  // Level 1
    message Inner {   // Level 2
      int32 ival = 1;
      bool  booly = 2;
    }
  }
}
```

# メッセージ型を更新する

もしあるメッセージ型がもはやあなたのニーズに合わなくなった時――例えば，追加のフィールドが欲しくなった時――でも古いフォーマットによって作成されたコードも依然として使いたい時，心配は無用だ．既にあるコードを破壊せずにメッセージ型を更新するのは非常に単純である．ただ以下のルールを覚えておけ：

- 既に存在するいかなるフィールドの数値タグをも変えてはならない．

- 新しいフィールドを追加する場合，あなたの”古い”メッセージフォーマットを使っているコードによってシリアライズされた全てのメッセージは，依然として新しく生成されたコードによってもパースすることができる．新しいコードが古いコードによって生成されたメッセージと正しく相互作用できるように，それらの要素についての[デフォルト値](#default)については留意しなければならない．同様に，新しいコードによって生成されたメッセージは古いコードによってパースすることができる：古いバイナリはパース時に単に新しいフィールドを無視する．詳細は[未知のフィールド](#unknowns)のセクションを見よ．

- フィールドは，更新されたメッセージ型でタグ値が再使用されていない限り，取り除くことができる．フィールドを削除する代わりにリネームすることもあるかもしれない．例えば "OBSOLETE_" というプリフィクスをつけたり，タグを [reserved](#reserved) にするなど．これにより未来のユーザがうっかりその番号を再使用してしまうことを防げる．

- `int32`, `uint32`, `int64`, `uint64`, `bool` は全て互換である――即ち，前方あるいは後方互換性を壊すことなく，フィールドの型をこれらの一つから他のものへ変更することができる．もし対応する型に一致しないワイヤから数値がパースされた場合，C++ で数値をその型にキャストしたのと同じような効果が得られる（例えば 64 ビットの数が int32 として読まれた場合，32 ビットに切り詰められる）．

- `sint32` と `sint64` は互換だが，他の整数型とは互換でない．

- `stirng` と `bytes` は，bytes が有効な UTF-8 である場合に限り互換である．

- 埋め込まれたメッセージは，もし bytes がそのメッセージのエンコードされたバージョンを含んでいれば，`bytes` と互換である．

- `fixed32` は `sfixed32` と互換である．また，`fixed64` と `sfixed64` も互換である．

- `enum` は `int32`, `uint32`, `int64`, `uint64` と，ワイヤフォーマットの面において互換である（ただしもしフィットしなければ切り詰められる）．しかしメッセージがデシリアライズされた時，クライアントのコードはそれらを異なるように扱うかもしれないことに注意されたい：例えば，認識されない proto3の `enum` 型はメッセージ中で保持はされるが，メッセージがデシリアライズされた時にどう表されるかは言語依存である．Int フィールドは常に単にそれらの値を保存する．

# 未知のフィールド <a name="unknowns"></a>

未知の (unknown) フィールドは，パーサが認識しないフィールドを表す，正しいプロトコルバッファーのシリアライズデータである．例えば，古いバイナリが新しいフィールドを持った新しいバイナリによって送られたデータをパースする際，それらの新しいフィールドは古いバイナリ中では未知のフィールドとなる．

Proto3 の実装では未知のフィールドを含むメッセージをパースすることはできるが，実装はそれらの未知のフィールドの保持についてはサポートするかもしれないし，しないかもしれない．保持されたかどうかわからない未知のフィールドに依拠するべきではない．殆どの Google プロトコルバッファーの実装では，proto3 に於ける未知のフィールドに，対応する proto ランタイムを通じてアクセスすることはできない．またデシリアライズ時に落とされるか，忘れられる．これは [proto2](https://developers.google.com/protocol-buffers/docs/proto) の挙動とは異なる．proto2 では，未知のフィールドは常に保持され，メッセージと合わせてシリアライズされる．

# Any

`Any` メッセージ型を用いると，メッセージを埋め込まれた型として，それらの .proto 定義を持つことなく利用することができる．`Any` は，任意のシリアライズされたメッセージを，グローバルにユニークな識別子として働きそのメッセージ型を解決する URL とともに，`bytes` として持つ．`Any` 型を使うためには，`google/protobuf/any.proto` をインポートする必要がある．

```protobuf
import "google/protobuf/any.proto";

message ErrorStatus {
  string message = 1;
  repeated google.protobuf.Any details = 2;
}
```

与えられたメッセージ型についてのデフォルトの型 URL は `type.googleapis.com/packagename.messagename` である．

それぞれの言語実装は，型安全な方法で Any 値をパックしたりアンパックするために．ランタイムライブラリヘルパーをサポートするだろう．例えば Java では，Any 型は特別な `pack()` と `unpack()` アクセサを持ち，一方 C++ では `PackFrom()` と `UnpackTo()` メソッドを持つだろう．

```cpp
// Storing an arbitrary message type in Any.
NetworkErrorDetails details = ...;
ErrorStatus status;
status.add_details()->PackFrom(details);

// Reading an arbitrary message from Any.
ErrorStatus status = ...;
for (const Any& detail : status.details()) {
  if (detail.Is<NetworkErrorDetails>()) {
    NetworkErrorDetails network_error;
    detail.UnpackTo(&network_error);
    ... processing network_error ...
  }
}
```

**現在，Any 型についてのランタイムライブラリは開発中である．**

もし既に [proto2 syntax](https://developers.google.com/protocol-buffers/docs/proto) に通じているならば，Any 型は [extensions](https://developers.google.com/protocol-buffers/docs/proto#extensions) を置き換えることができる．

# oneof

もしたくさんのフィールドを持つメッセージがあり，同時に多くても一つのフィールドのみがセットされるようならば，この振る舞いを oneof によって強制させメモリを節約することができる．

oneof のフィールドは，全てのフィールドがメモリを共有していて，また同時に多くても一つのフィールドのみがセットされること以外は，普通のフィールドと同じである．oneof のあるメンバをセットすると，自動的に他の全てのメンバはクリアされる．どの値がセットされているかは特別な `case()` 乃至 `WhichOneof()` メソッドを用いることで確認できる．

## oneof を使う

`.proto` ファイル中で oneof を定義するためには名前の前に `oneof` キーワードをつける．次の例では `test_oneof` という oneof を定義している：

```protobuf
message SampleMessage {
  oneof test_oneof {
    string name = 4;
    SubMessage sub_message = 9;
  }
}
```

それから oneof のフィールドを oneof の定義に加えている．任意の型のフィールドを加えることができるが，`repeated` フィールドを使うことはできない．

生成されたコードでは，oneof のフィールドは普通のフィールドと同じゲッターとセッターを持つ．また oneof のどの値が（もしセットされているならば）セットされているかをチェックする特別なメソッドもある．oneof API についての詳細は [API reference](https://developers.google.com/protocol-buffers/docs/reference/overview) を参照されたい．

## oneof の特徴

- oneof のフィールドをセットすると自動的にその oneof の他の全てのフィールドがクリアされる．つまり，幾つかの oneof フィールドをセットすると，最後にセットしたフィールドのみが値を持つことになる．

```cpp
SampleMessage message;
message.set_name("name");
CHECK(message.has_name());
message.mutable_sub_message();   // Will clear name field.
CHECK(!message.has_name());
```

- もしパーサがワイヤ上で同じ oneof の複数のメンバに遭遇した場合，最後に目撃したメンバのみがパースされたメッセージに使われる．

- oneof は `repeated` たりえない．

- Reflection API は oneof フィールドの役に立つ．

- C++ を使っているならば，メモリクラッシュを起こさないように注意せよ．次のサンプルコードはクラッシュする．なぜならば， `set_name()` メソッドを読んだことにより `sub_message` は既に削除されているからである．

  ```cpp
  SampleMessage message;
  SubMessage* sub_message = message.mutable_sub_message();
  message.set_name("name");      // Will delete sub_message
  sub_message->set_...            // Crashes here
```

- 再び C++ についてだが，oneof の二つのメッセージを `Swap()` した場合，各メッセージはもう一方の oneof の状態となる．以下の例では，`msg1` は `sub_message` を持ち，`msg2` は `name` を持つことになる．

  ```protobuf
  SampleMessage msg1;
  msg1.set_name("name");
  SampleMessage msg2;
  msg2.mutable_sub_message();
  msg1.swap(&msg2);
  CHECK(msg1.has_sub_message());
  CHECK(msg2.has_name());
  ```

## 後方互換性問題

oneof のフィールドを加えたり取り除くときは注意せよ．oneof の値チェックで `None` / `NOT_SET` が帰ってきた場合，その oneof はまだセットされていないか，もしくは oneof の異なるバージョンのフィールドがセットされていたということである．ワイヤ上の未知のフィールドが oneof のメンバかどうか知る方法はないため，この違いを伝える方法はない．

## タグ再使用問題

- **oneof の中へもしくは外へフィールドを動かす**: メッセージがシリアライズされパースされた後，幾つかの情報は失われるかもしれない（幾つかのフィールドはクリアされるだろう）．

- **oneof のフィールドを削除して後で戻す**: メッセージがシリアライズされパースされた後，現在セットされているフィールドはクリアされるかもしれない．

- **oneof を分割したりマージする**: これは通常のフィールドを移動させる問題と似ている．

# map

データ定義の一部として連想マップを使いたくなった場合，プロトコルバッファーは便利な短縮記法を用意している：

```protobuf
map<key_type, value_type> map_field = N;
```

ここで `key_type` は任意の整数もしくは文字列型（即ち，小数点型と `bytes` を除く任意のスカラー型）である．`value_type` は他のマップを除く任意の型である．

例えば，各 `Project` メッセージが文字列のキーに関連づいたプロジェクトのマップを作りたくなれば，次のように定義できる：

```protobuf
map<string, Project> projects = 3;
```

- map フィールドは `repeated` たりえない．

- map 値のワイヤフォーマット順番と map イテレーション順番は定義されていない，即ち map のアイテムが特定の順番になっていることに依拠してはならない．

- `.proto` のテキストフォーマットが生成される時，map はキーによってソートされる．数値キーは数字によってソートされる．

- ワイヤからパースする時やマージする時，もし重複するキーが存在すれば最後に目撃されたキーが用いられる．テキストフォーマットから map をパースする時，もし重複するキーが存在すればパースは失敗する可能性がある．

## 後方互換性

map シンタックスはワイヤ上では次に等しい．従って map をサポートしていないプロトコルバッファーの実装もあなたのデータを扱うことができる：

```protobuf
message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
}

repeated MapFieldEntry map_field = N;
```

# パッケージ

プロトコルメッセージ型の間での名前衝突を避けるために，`.proto` ファイルに任意で `package` 指定子を加えることができる．

```protobuf
package foo.bar;
message Open { ... }
```

するとメッセージ型のフィールド定義でパッケージ指定子を用いることができる：

```protobuf
message Foo {
  ...
  foo.bar.Open open = 1;
  ...
}
```

パッケージ指定子が生成コードにどう影響するかは言語による．

- **C++** では生成されるクラスは C++ 名前空間内でラップされる．例えば，`Open` は `foo::bar` 名前空間内に配置されるだろう．

- **Java** では，`.proto` ファイルに明示的に `option java_package` を加えない限り，パッケージは Java パッケージとして用いられる．

- **Python** では，パッケージ命令は無視される．Python モジュールはファイルシステム内での配置によって体系づけられるからである．

- **Go** では，`.proto` ファイルに明示的に `option go_package` を加えない限り，パッケージは Go パッケージ名として使われる．

- **Ruby** では，生成されたクラスはネストされた Ruby 名前空間内でラップされる．ただし，Ruby の要求する大文字化スタイルに変換される（最初の文字が大文字になる；もし最初の文字がレターでなければ `PB_` が先頭に追加される）．例えば，`Open` は `Foo:Bar` 名前空間内に配置されるだろう．

- **JavaNano** では，`.proto` ファイルに明示的に `option java_package` を加えない限り，パッケージは Java パッケージとして用いられる．

- **C#** では，`.proto` ファイルに明示的に `option csharp_package` を加えない限り，パッケージはパスカルケースに変換された後に名前空間として用いられる．例えば，`Open` は `Foo.Bar` 名前空間内に配置されるだろう．

## パッケージと名前解決

プロトコルバッファー言語における型名解決は C++ のそれに似ている：まず最内のスコープが検索され，それから二番目に内側の，以後同様．それぞれのパッケージはその親パッケージに対して”内側にある”と見做される．先頭の `.`（例えば `.foo.bar.Baz`）は，代わりに最外のスコープからスタートすることを意味する．

プロトコルバッファーコンパイラはインポートされた `.proto` ファイルをパースすることで全ての型名を解決する．各言語のコード生成器は，たとえ異なるスコープルールを持っているとしても，その言語において各型をどのように参照するかを知っている．

# サービス定義

メッセージ型を RPC（リモートプロシージャコール）システムで使いたい場合，`.proto` ファイルで RPC サービスのインターフェイスを定義することができる．プロトコルバッファーコンパイラは選択した言語でサービスインターフェイスコードとスタブを生成する．例えば，`SearchRequest` を引数に取り `SearchResponse` を返すメソッドを持つ RPC サービスを定義したくなったら，`.proto` ファイルに次のように定義する：

```protobuf
service SearchService {
  rpc Search (SearchRequest) returns (SearchResponse);
}
```

プロトコルバッファーを用いた最も簡単な RPC システムは [gRPC](https://github.com/grpc/grpc-experiments) である．gRPC はプラットフォーム・ニュートラルでオープンソースの RPC システムであり，Google によって開発されている．gRPC はプロトコルバッファーを用いることで特によく働く．また特別なプロトコルバッファープラグインを用いることで `.proto` ファイルから直接関連する RPC コードを生成することができる．

もし gRPC を使いたくないならば，あなたの RPC 実装とともにプロトコルバッファーを用いることもできる．詳細については [Proto2 Language Guide](https://developers.google.com/protocol-buffers/docs/proto#services) を参照のこと．

プロトコルバッファーに対する RPC 実装を開発しているたくさんのサードパーティがまた存在する．我々が知っているプロジェクトのリンクのリストについては [third-party add-ons wiki page](https://github.com/google/protobuf/blob/master/docs/third_party.md) を見よ．

# JSON マッピング

proto3 は標準的な JSON エンコードをサポートしている．これによりシステム間でデータを共有することが容易になる．エンコーディングはタイプ・バイ・タイプの基準で以下の表に示されている．

プロトコルバッファーへのパースに於いて，もし JSON エンコードされたデータ中である値が見つからなかったり `null` だった場合，適当な[デフォルト値](#default)として解釈される．もしあるフィールドがプロトコルバッファーでデフォルト値を持っている場合，デフォルトでは空間の節約のために JSON エンコードされたデータではそれは省かれる．実装は，JSON エンコードされた出力に於いてデフォルト値を持つフィールドを省くオプションを提供するかもしれない．

| proto3 | JSON | JSON example | Notes |
|:--|:--|:--|:--|
| message | object | {"fBar": v, "g": null, …} | JSON オブジェクトを生成する．メッセージフィールド名はローワーキャメルケースにマップされ JSON オブジェクトのキーとなる．null は受容可能で，対応するフィールド型のデフォルト値として扱われる． |
| enum | string | "FOO_BAR" | proto で指定された enum 値の名前が使われる． |
| map<K,V> | object | {"k": v, …} | 全てのキーは文字列に変換される． |
| repeated V | array | [v, …] | null は受容可能で，空リストとして扱われる． |
| bool | true, false | true, false| |
| string | string | "Hello World!" | |
| bytes | base64 string | "YWJjMTIzIT8kKiYoKSctPUB+" | JSON 値はパディング付き標準 base64 エンコーディングを用いて文字列にエンコードされたものになる．パディングあり / なし標準 or URL 安全 base64 エンコードの何れも受容可能． |
| int32, fixed32, uint32 | number | 1, -10, 0 | JSON 値は小数になる．数値 or 文字列が受容可能． |
| int64, fixed64, uint64 | string | "1", "-10" | JSON 値は小数の文字列になる．数値 or 文字列が受容可能． |
| float, double | number | 1.1, -10.0, 0, "NaN", "Infinity" | JSON 値は数値か特別な値 "NaN", "Infinity", "-Infinity" の何れかとなる．数値 or 文字列が受容可能．指数表記も受容可能． |
| Any | object | {"@type": "url", "f": v, … } | Any が特別な JSON マッピングを持つ値を含んでいる場合，それは次のように変換される：{"@type": xxx, "value": yyy }．それ以外では，値は JSON オブジェクトに変換され，"@type" フィールドが実際のデータ型を示すために挿入される． |
| Timestamp | string | "1972-01-01T10:00:20.021Z" | RFC 3339 を用いる：出力は常に Z-正規化され 0, 3, 6, 9 の何れかの小数桁を用いる． |
| Duration | string | "1.000340012s", "1s" | 出力は要求される精度に依存して常に 0, 3, 6, 9 の何れかの小数桁を含む．ナノ秒精度にフィットしている限り任意の小数桁 (もしくは none) を受容する． |
| Struct | object | { … } | 任意の JSON オブジェクト．struct.proto を見よ． |
| Wrapper types | various types | 2, "2", "foo", true, "true", null, 0, … | ラッパーはラップされたプリミティブ型と同じ JSON での表現を用いる．ただし null は許容され，データ変換と転送の間保持される． |
| FieldMask | string | "f.fooBar,h" | fieldmask.proto を見よ． |
| ListValue | array | [foo, bar, …] ||
| Value | value | | 任意の JSON 値． |
| NullValue | null | | JSON null |

# オプション

`proto` ファイル内の個々の宣言には幾つかのオプションによって注釈をつけることができる．オプションは定義の全体の意味は変化させないが，それがある文脈においてどのように扱われるかについて影響を与える．利用可能なオプションのリストは `google/protobuf/descriptor.proto` に定義されている．

幾つかのオプションはファイルレベルのオプションであり，それらはトップレベルスコープに書かれなければならない．即ち，メッセージや enum, サービス定義内に書いてはいけない．また幾つかのオプションはメッセージレベルのオプションであり，メッセージ定義の中に書かれなければならない．フィールドレベルのオプションはフィールド定義の中に書かれなければならない．オプションはまた enum 型，enum 値，サービス型，サービスメソッド上にも書かれうる．しかしながら，今の所これらについて有用なオプションはない．

以下は幾つかの最も一般的に使われるオプションである：

- `java_package`（ファイルオプション）：生成された Java クラスで用いたいパッケージ名．もし `.proto` ファイルに明示的に `java_package` オプションが与えられなければ，デフォルトで proto パッケージ（`.proto` ファイル中に "package" キーワードを用いることよって指定される）が使われる．しかし，proto パッケージは一般に良い Java パッケージを生成しない．これは，proto パッケージはリバースドメイン名で始まることを予期しないからである．もし Java コードを生成しない場合は，このオプションは何の効果もない．

  ```protobuf
  option java_package = "com.example.foo";
  ```

- `java_multiple_files`（ファイルオプション）：トップレベルメッセージ，enum, サービスを，`.proto` ファイルの名前がついた外側クラスの内側ではなく，パッケージレベルで定義されるようにする．

  ```protobuf
  option java_multiple_files = true;
  ```

- `java_outer_classname`（ファイルオプション）：生成したい最外の Java クラス（従ってそのファイル名）のクラス名．もし `.proto` ファイルに明示的に `java_outer_classname` オプションが与えられなければ，そのクラス名は `.proto` ファイル名をキャメルケースに変換したもの（即ち `foo_bar.proto` であれば `FooBar.java`）が使われる．もし Java コードを生成しない場合は，このオプションは何の効果もない．

- `optimize_for`（ファイルオプション）：`SPPED`, `CODE_SIZE`, `LITE_RUNTIME` の何れかに設定できる．これは C++ と Java コード生成器（もしくは他のサードパーティーによる生成器）に影響を与える．

  - `SPEED`（デフォルト）：プロトコルバッファコンパイラはあなたのメッセージ型についてシリアライズ，パース，そして他の一般的な操作を行うためのコードを生成する．このコードは高度に最適化されている．

  - `CODE_SIZE`：プロトコルバッファコンパイラは最小のクラスを生成し，シリアライズ，パース，他の様々な操作については共有の，リフレクションベースのコードに依拠する．生成されたコードは従って `SPEED` の時よりかなり小さくなるが，操作は遅くなる．クラスはなお `SPEED` モードの時と全く同じ公開 API を実装する．このモードは非常に沢山の `.proto` ファイルを含み，それらすべてがむやみに速い必要がないようなアプリケーションに於いて最も便利である．

  - `LITE_RUNTIME`：プロトコルバッファコンパイラは”軽い”ランタイムライブラリのみに依存するクラスを生成する（即ち `libprotobuf` の代わりに `libprotobuf-lite` を用いる）．軽いランタイムは完全なライブラリに比べるとかなり小さい（おおよそ桁レベルで小さい）が，デスクリプタやリフレクションのような特定の機能を省いている．これは特に携帯電話のような制限されたプラットフォームに於いて走るアプリケーションに於いて有用である．コンパイラはなお `SPPED` モードと同様の全てのメソッドの速い実装を生成する．各言語において，生成されたクラスは `MessageLite` インターフェースのみを実装し，これは完全な `Message` インターフェースの一部のみを提供する．

  ```protobuf
  option optimize_for = CODE_SIZE;
  ```

- `cc_enable_arenas`（ファイルオプション）：C++ 生成コードのための [arena allocation](https://developers.google.com/protocol-buffers/docs/reference/arenas) を有効にする．

- `objc_class_prefix`（ファイルオプション）：この `.proto` から生成される全ての Objective-C クラスと enum に対して接頭される Objective-C クラスプリフィクスを設定する．デフォルト値はなし．[Apple のリコメンド](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html#//apple_ref/doc/uid/TP40011210-CH10-SW4)に従って 3-5 文字の大文字を接頭することが望ましい．ただし全ての 2 文字の接頭辞は Apple によって予約されている．

- `deprecated`（フィールドオプション）：これが `true` になっていることは，そのフィールドが非推奨であり新しいコードによって使われるべきでないということを意味する．殆どの言語では実際に何か影響を与えるわけではない．Java では，これは `@Deprecated` 注釈となる．将来，他の言語についてのコード生成器もフィールドアクセサに非推奨注釈を生成するようになるかもしれない．するとそのフィールドを使おうとしたコードをコンパイルした時，警告が発せられるようになるだろう．もしフィールドが誰にも使用されておらず，新しいユーザに使わせたくないのであれば，フィールド宣言に `reserved` を加えることを検討せよ．

  ```protobuf
  int32 old_field = 6 [deprecated=true];
  ```

## カスタムオプション

プロトコルバッファーはまたあなた独自のオプションを定義したり使用することを許す．これは**拡張機能**であり殆どの人々にとっては必要ない．もし独自のオプションを作成したいのであれば [Proto2 Language Guide](https://developers.google.com/protocol-buffers/docs/proto.html#customoptions) を参照せよ．カスタムオプションの作成には [extensions](https://developers.google.com/protocol-buffers/docs/proto#extensions) を使うが，これは proto3 ではカスタムオプションの作成に於いてのみ許可されていることに留意されたい．

# クラスを生成する

Java, Python, C++, Go, Ruby, JavaNano, Objective-C, C# のコードを生成するためには，`.proto` ファイルでメッセージ型を定義し，プロトコルバッファーコンパイラ `protoc` にかける必要がある．もしコンパイラをまだインストールしていないのであれば，[download the package](https://developers.google.com/protocol-buffers/docs/downloads.html) で README の指示に従え．Go については．さらに特別なコード生成プラグインをインストールする必要がある：GitHub 上のレポジトリ [golang/protobuf](https://github.com/golang/protobuf/) でこれとインストール説明が得られる．

プロトコルバッファコンパイラは次のようにして呼び出される：

```bash
protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --javanano_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto
```

- `IMPORT_PATH` は ，`import` 命令を解決するときに `.proto` ファイルを探すディレクトリを指定する．省略された場合，カレントディレクトリが用いられる．`--proto_path` オプションを複数回も用いることで複数のインポートディレクトリを指定することもできる；それらは指定された順番で検索される．`-I=IMPORT_PATH` は `--proto_path` の省略形として使うことができる．

- 一つ以上の出力指示を与えることができる．

  - `--cpp_out` は `DST_DIR` 内に C++ コードを生成する．詳細は [C++ generated code reference](https://developers.google.com/protocol-buffers/docs/reference/cpp-generated) を参照．

  - `--java_out` は `DST_DIR` 内に Java コードを生成する．詳細は [Java generated code reference](https://developers.google.com/protocol-buffers/docs/reference/java-generated) を参照．

  - `--python_out` は `DST_DIR` 内に Python コードを生成する．詳細は [Python generated code reference](https://developers.google.com/protocol-buffers/docs/reference/python-generated) を参照．

  - `--go_out` は `DST_DIR` 内に Go コードを生成する．詳細は [Go generated code reference](https://developers.google.com/protocol-buffers/docs/reference/go-generated) を参照．

  - `--ruby_out` は `DST_DIR` 内に Ruby コードを生成する．リファレンスは近日公開！

  - `--javanano_out` は `DST_DIR` 内に JavaNano コードを生成する．JavaNano コード生成器は出力をカスタマイズするための多くのオプションを持つ：詳細は README を参照のこと．リファレンスは近日公開！

  - `--objc_out` は `DST_DIR` 内に Objective-C コードを生成する．詳細は [Objective-C generated code reference](https://developers.google.com/protocol-buffers/docs/reference/objective-c-generated) を参照．

  - `--csharp_out` は `DST_DIR` 内に C# コードを生成する．詳細は [C# generated code reference](https://developers.google.com/protocol-buffers/docs/reference/csharp-generated) を参照．

  - `--php_out` は `DST_DIR` 内に PHP コードを生成する．詳細は [PHP generated code reference](https://developers.google.com/protocol-buffers/docs/reference/php-generated) を参照．

特別な便宜のために，もし `DST_DIR` が `.zip` や `.jar` で終わっているのであれば，コンパイラは出力を与えられた名前の一つの ZIP アーカイブファイルとする．`.jar` 出力もまた Java JAR 仕様の要求するところに応じてマニフェストファイルが与えられる．ただし出力アーカイブが既に存在している場合は上書きされる；コンパイラは既存アーカイブにファイルを追加できるほど賢くはない．

- 入力として一つ以上の `.proto` ファイルが与えられなければならない．複数の `.proto` ファイルを一度に指定することもできる．ファイルがカレントディレクトリからの相対名で与えられるとしても，コンパイラが正しい名前を決定できるように，各ファイルは `IMPORT_PATH` の中のどこかの場所にいなければならない．