1. 概要

この記事では、 Google Protocol Buffer (protobuf)–よく知られている言語に依存しないバイナリデータ形式について説明します。 プロトコルを使用してファイルを定義し、次にそのプロトコルを使用して、Java、C ++、C#、Go、Pythonなどの言語でコードを生成できます。

これは、フォーマット自体の紹介記事です。 Spring Webアプリケーションでこの形式を使用する方法を知りたい場合は、この記事を参照してください。

2. Mavenの依存関係の定義

プロトコルバッファをJavaで使用するには、Maven依存関係をprotobuf-javaに追加する必要があります。

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>${protobuf.version}</version>
</dependency>

<properties>
    <protobuf.version>3.2.0</protobuf.version>
</properties>

3. プロトコルの定義

例から始めましょう。 非常に単純なプロトコルをprotobuf形式で定義できます。

message Person {
    required string name = 1;
}

これは、 Person タイプの単純なメッセージのプロトコルであり、必須フィールドは1つだけです。名前は文字列タイプです。

プロトコルを定義するより複雑な例を見てみましょう。 個人の詳細をprotobuf形式で保存する必要があるとしましょう。

パッケージprotobuf;

package protobuf;

option java_package = "com.baeldung.protobuf";
option java_outer_classname = "AddressBookProtos";

message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;

    repeated string numbers = 4;
}

message AddressBook {
    repeated Person people = 1;
}

私たちのプロトコルは、 PersonAddressBookの2種類のデータで構成されています。コードを生成した後(これについては後のセクションで詳しく説明します)、これらのクラスは内部クラスになります。 AddressBookProtosクラス。

必須のフィールドを定義する場合、つまり、そのようなフィールドなしでオブジェクトを作成すると例外が発生する場合、必須のキーワードを使用する必要があります。

オプションのキーワードを使用してフィールドを作成すると、このフィールドを設定する必要がなくなります。 繰り返しキーワードは、可変サイズの配列型です。

すべてのフィールドにインデックスが付けられます。番号1で示されるフィールドは、バイナリファイルの最初のフィールドとして保存されます。 2でマークされたフィールドは、次に保存されます。 これにより、フィールドがメモリにどのように配置されるかをより適切に制御できます。

4. ProtobufファイルからのJavaコードの生成

ファイルを定義したら、そこからコードを生成できます。

まず、マシンにprotobufをインストールする必要があります。 これを実行すると、protocコマンドを実行してコードを生成できます。

protoc -I=. --java_out=. addressbook.proto

protoc コマンドは、 addressbook.proto fileからJava出力ファイルを生成します。-I オプションは、-IオプションがX166X]プロトファイルが存在します。 java-out は、生成されたクラスが作成されるディレクトリを指定します。

生成されたクラスには、定義されたメッセージのセッター、ゲッター、コンストラクター、ビルダーが含まれます。 また、protobufファイルを保存し、バイナリ形式からJavaクラスに逆シリアル化するためのいくつかのutilメソッドもあります。

5. Protobuf定義メッセージのインスタンスの作成

生成されたコードを使用して、PersonクラスのJavaインスタンスを簡単に作成できます。

String email = "[email protected]";
int id = new Random().nextInt();
String name = "Michael Program";
String number = "01234567890";
AddressBookProtos.Person person =
  AddressBookProtos.Person.newBuilder()
    .setId(id)
    .setName(name)
    .setEmail(email)
    .addNumbers(number)
    .build();

assertEquals(person.getEmail(), email);
assertEquals(person.getId(), id);
assertEquals(person.getName(), name);
assertEquals(person.getNumbers(0), number);

目的のメッセージタイプでnewBuilder()メソッドを使用して、流暢なビルダーを作成できます。 すべての必須フィールドを設定した後、 build()メソッドを呼び出して、Personクラスのインスタンスを作成できます。

6. Protobufのシリアル化と逆シリアル化

Person クラスのインスタンスを作成したら、作成したプロトコルと互換性のあるバイナリ形式でディスクに保存します。 AddressBook クラスのインスタンスを作成し、そのオブジェクトに1人の人物を追加するとします。

次に、そのファイルをディスクに保存します。自動生成されたコードには、 writeTo()utilメソッドがあります。これを使用できます。

AddressBookProtos.AddressBook addressBook 
  = AddressBookProtos.AddressBook.newBuilder().addPeople(person).build();
FileOutputStream fos = new FileOutputStream(filePath);
addressBook.writeTo(fos);

そのメソッドを実行した後、オブジェクトはバイナリ形式にシリアル化され、ディスクに保存されます。 そのデータをディスクからロードし、それを AddressBook オブジェクトに逆シリアル化するには、 mergeFrom()メソッドを使用できます。

AddressBookProtos.AddressBook deserialized
  = AddressBookProtos.AddressBook.newBuilder()
    .mergeFrom(new FileInputStream(filePath)).build();
 
assertEquals(deserialized.getPeople(0).getEmail(), email);
assertEquals(deserialized.getPeople(0).getId(), id);
assertEquals(deserialized.getPeople(0).getName(), name);
assertEquals(deserialized.getPeople(0).getNumbers(0), number);

7. 結論

この簡単な記事では、データをバイナリ形式で記述および保存するための標準であるGoogleProtocolBufferを紹介しました。

単純なプロトコルを作成し、定義されたプロトコルに準拠するJavaインスタンスを作成しました。 次に、protobufを使用してオブジェクトをシリアル化および逆シリアル化する方法を確認しました。

これらすべての例とコードスニペットの実装は、 GitHubプロジェクトにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。