複数メッセージタイプの宣言、フィールド型での利用

ここからは、protoファイルのさらに進んだ記述方法を見ていくとしよう。

以下では、様々な記述方法を用いて、先ほどのサンプル(Persons.proto)を修正していく。なお、修正後のprotoファイルは、それを利用するJavaプログラムと併せて本稿の最後に全文掲載するので、そちらも参照して欲しい。

メッセージタイプは、一つのファイル内に複数定義することができる。例えば、先ほどのPersonクラスを修正し、名前を表すフィールドには専用の「Name」型を利用するとしよう。同じPersons.protoファイル内でName型を宣言し、Person内で利用していることに注目。

message Person {
  // Name型を用いてフィールドを宣言
  required Name name = 1;
  optional int32 age = 2;
}
// 名前を表す構造化データ
message Name {
  required string first_name = 1;
  required string last_name = 2;
  optional string middle_name = 3;
}

また、他のメッセージタイプ内に入れ子で宣言することもできる。

message Person {
  // 他の型の中でメッセージタイプを宣言
  message Name {
    required string first_name = 1;
    required string last_name = 2;
    optional string middle_name = 3;
  }
  required Name name = 1;
  optional int32 age = 2;
}

このようにすると、生成されたJavaコード内でもNameクラスはPersonの入れ子クラスとなる(Persons.Person.Nameクラスになるということだ)。

Enumの使用

値のパターンがあらかじめ決まっている型に関しては、列挙値(enum)を使用することも可能だ。例えば、性別を表すGender型を作成してみる。「enum Gender」に続いて中括弧でブロックを宣言し、その中に「名前=整数値;」を複数記述することでenumを作成することができる。

enum Gender {
  MALE = 0;
  FEMALE = 1;
}
message Person {
  required Name name = 1;
  optional int32 age = 2;

  // enum型を利用して宣言
  optional Gender gender = 3;
}

また、他の型宣言中に、入れ子でenumの宣言を行うことも可能だ。

message Person {
  required Name name = 1;
  optional int32 age = 2;
  // 他の型の中でenumを宣言
  enum Gender {
    MALE = 0;
    FEMALE = 1;
  }
  // enum型を利用して宣言
  optional Gender gender = 3;
}

こうして作成したenumは、Javaソースコード中でもenumとして扱うことができる。

パッケージとインポート

メッセージタイプの名前が衝突しないように、パッケージを指定することもできる。パッケージは、ファイル先頭で「package パッケージ名;」と指定するだけだ。

package mycom;

message Person {
  ...(略)...
}

また、他のファイルをインポートすることも可能だ。そのためには、import文を用いてprotoファイルへのパスを指定する。

package mycom;

import "path/to/another.proto"

message Person {
  ...
}

import文に指定されたprotoファイルは、protocコマンドの-I(もしくは--import_path)オプションで指定されたディレクトリ(省略時はカレントディレクトリ)を起点として検索される。以下の例では、「../common」ディレクトリをimportの検索パスとして指定している。

> protoc -I ../common --java_out java Persons.proto

デフォルト値

各フィールドには、値が指定されなかった場合に使用するデフォルト値を設定することもできる。その構文は以下の通りだ。

// タグのあとの"[default = MALE]"に注目
optional Gender gender = 3 [default = MALE];

タグの後に続けて大括弧で囲み、"default = 値"という書式を用いる。これで、値の省略時にはこの値が用いられるようになる。

ちなみに、デフォルト値を指定しなかった場合のoptionalフィールドの値はどうなるかと言うと、型に応じた適切なデフォルト値が使用される。

  • bool: false
  • string: 空の文字列
  • 数値型: ゼロ