注: このサイトは非推奨になりました。このサイトは 2023 年 1 月 31 日を過ぎると停止され、トラフィックは https://protobuf.dev の新しいサイトにリダイレクトされます。その間、更新は protobuf.dev のみに行われます。

概要

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

プロトコル バッファは、言語やプラットフォームに依存しない、拡張可能なメカニズムを提供します。これにより、前方互換性および下位互換性のある方法で構造化データがシリアル化されます。JSON に似ていますが、小さくて高速であり、ネイティブ言語バインディングを生成します。

プロトコル バッファは、定義言語(.proto ファイルで作成)、proto コンパイラがデータとやり取りするために生成するコード、言語固有のランタイム ライブラリ、ファイルに書き込まれる(またはネットワーク接続を介して送信される)データのシリアル化形式を組み合わせたものです。

プロトコル バッファで解決される問題は何か

プロトコル バッファは、数メガバイトまでの型付き構造化データのパケットにシリアル化形式を提供します。この形式は、エフェメラル ネットワーク トラフィックと長期データ ストレージの両方に適しています。既存のデータを無効化したり、コードを更新したりすることなく、プロトコル バッファを新しい情報で拡張できます。

プロトコル バッファは、Google で最もよく使用されるデータ形式です。これらは、サーバー間通信や、ディスク上のデータのアーカイブ ストレージにも広く使用されます。プロトコル バッファのメッセージとサービスは、エンジニアが作成した .proto ファイルによって記述されます。次に message の例を示します。

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

proto コンパイラは、ビルド時に .proto ファイルで呼び出され、さまざまなプログラミング言語(このトピックの後半の言語間の互換性で説明します)でコードを生成し、対応するプロトコル バッファを操作します。生成される各クラスには、フィールドごとの単純なアクセサと、未加工のバイトとの間で構造全体をシリアル化および解析するメソッドが含まれています。生成されたメソッドを使用した例を以下に示します。

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

プロトコル バッファは Google のあらゆるサービスで広範囲に使用され、その中のデータが一定期間保持される可能性があるため、下位互換性を維持することが非常に重要です。プロトコル バッファを使用すると、既存のサービスを中断することなく、任意のプロトコル バッファに新しいフィールドの追加や既存のフィールドの削除など、変更をシームレスにサポートできます。このトピックについて詳しくは、このトピックで後述するコードを更新せずに Proto 定義を更新するをご覧ください。

プロトコル バッファを使用するメリットは何ですか?

プロトコル バッファは、言語やプラットフォームに依存せず、拡張可能な方法で、構造化されたレコードのような型付きのデータをシリアル化する必要がある状況に最適です。これらは通常、通信プロトコル(gRPC とともに)を定義する場合やデータ ストレージに使用されます。

プロトコル バッファを使用すると、次のようなメリットがあります。

  • コンパクトなデータ ストレージ
  • 高速解析
  • 多数のプログラミング言語での提供
  • 自動生成されたクラスで機能が最適化される

言語間互換性

サポートされている任意のプログラミング言語で記述されたコードで、同じメッセージを読み取ることができます。あるプラットフォーム上の Java プログラムが、あるソフトウェア システムからデータをキャプチャし、.proto 定義に基づいてシリアル化し、そのシリアル化されたデータから別のプラットフォームで実行されている別の Python アプリケーションで特定の値を抽出することができます。

以下の言語は、プロトコル バッファ コンパイラ(protoc)で直接サポートされています。

次の言語は Google でサポートされていますが、プロジェクトのソースコードは GitHub リポジトリにあります。protoc コンパイラは、以下の言語用のプラグインを使用します。

追加の言語は Google が直接サポートするのではなく、他の GitHub プロジェクトによってサポートされています。これらの言語については、プロトコル バッファ用のサードパーティ アドオンをご覧ください。

プロジェクト間のサポート

特定のプロジェクトのコードベース外にある .proto ファイルで message タイプを定義することで、プロジェクト間でプロトコル バッファを使用できます。即時チーム外で広く使用されると予想される message 型または列挙型を定義する場合は、依存関係なしで独自のファイルに入れることができます。

Google で広く使用されている proto 定義としては、timestamp.protostatus.proto などがあります。

コードを更新せずに Proto 定義を更新する

ソフトウェア プロダクトに下位互換性があることは標準的ですが、上位互換性を持たせることはあまりありません。.proto 定義を更新するときにシンプルな方法に従っていれば、新しく追加されたフィールドを無視して、古いコードで新しいメッセージが問題なく読み取られます。古いコードの場合、削除されたフィールドにはデフォルト値があり、削除された繰り返しフィールドは空になります。「繰り返し」フィールドの詳細については、このトピックの後半のプロトコル バッファの定義構文をご覧ください。

また、新しいコードは古いメッセージを透過的に読み取ります。新しいフィールドは古いメッセージには含まれません。このような場合、プロトコル バッファは妥当なデフォルト値を提供します。

プロトコル バッファが適していない状況

プロトコル バッファはすべてのデータに適合するわけではありません。具体的には、次のとおりです。

  • プロトコル バッファは、メッセージ全体を一度にメモリに読み込めることを前提とし、オブジェクト グラフよりも大きくなることはありません。数メガバイトを超えるデータについては、別のソリューションを検討してください。大規模なデータを扱う場合、シリアル化されたコピーが原因でデータのコピーが複数作成されることになり、メモリ使用量が予期せず急増する可能性があります。
  • プロトコル バッファがシリアル化されている場合、同じデータで多くの異なるシリアル化が行われる可能性があります。2 つのメッセージを比較して、完全に解析する必要があります。
  • メッセージは圧縮されません。メッセージは他のファイルと同様に圧縮または gzip で圧縮できますが、JPEG や PNG などの専用圧縮アルゴリズムを使用すると、適切な形式のデータ用にはるかに小さなファイルが生成されます。
  • 浮動小数点数値の大きな多次元配列を含む多くの科学的用途やエンジニアリング用途において、プロトコル バッファ メッセージはサイズと速度の両方で最大限に効率的ではありません。これらのアプリケーションでは、FITS などのフォーマットでオーバーヘッドが減少します。
  • プロトコル バッファは、Fortran や IDL などの科学技術計算で一般的なオブジェクト指向言語では十分にサポートされていません。
  • プロトコル バッファ メッセージは本質的にデータを自己記述するわけではありませんが、自己記述を実装するために完全に反映するスキーマを備えています。つまり、対応する .proto ファイルにアクセスできないと、これをまったく解釈できません。
  • プロトコル バッファは、組織の正式な標準ではありません。そのため、法律をベースとした法的要件やその他の要件がある環境での使用には適していません。

プロトコル バッファを使用するユーザー

外部から利用できる多くのプロジェクトでは、次のようなプロトコル バッファを使用します。

プロトコル バッファの仕組み

次の図は、プロトコル バッファを使用してデータを処理する方法を示しています。


図 1. プロトコル バッファのワークフロー

プロトコル バッファによって生成されるコードには、ファイルとストリームからデータを取得する方法、データから個々の値を抽出する方法、データが存在するかどうかを確認する方法、データをファイルまたはストリームにシリアル化できるその他の有用な関数を提供するユーティリティ メソッドが用意されています。

次のコードサンプルは、Java でのこのフローの例を示しています。前述のように、これは .proto 定義です。

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

この .proto ファイルをコンパイルすると、次の Java コードに示すように、新しいインスタンスの作成に使用できる Builder クラスが作成されます。

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

その後、プロトコル バッファが他の言語(C++ など)で作成するメソッドを使用してデータを逆シリアル化できます。

Person john;
fstream input(argv[1], ios::in | ios::binary);
john.ParseFromIstream(&input);
int id = john.id();
std::string name = john.name();
std::string email = john.email();

プロトコル バッファ定義の構文

.proto ファイルを定義するときに、フィールドを optional または repeated(proto2 と proto3)または singular(proto3)に指定できます。(フィールドを required に設定するオプションは、proto3 には存在しないため、proto2 では推奨されません)。詳細については、フィールド ルールの指定の「Required が Forever」をご覧ください。

フィールドのオプションまたは反復性を設定した後、データ型を指定します。プロトコル バッファは、整数、ブール値、浮動小数点数など、通常のプリミティブ データ型をサポートします。完全なリストについては、スカラー値型をご覧ください。

次のフィールドも使用できます。

  • message 型。データセットを繰り返す場合など、定義の一部をネストできます。
  • enum 型。選択する値のセットを指定できます。
  • メッセージに多くのオプション フィールドがあり、最大 1 つのフィールドが同時に設定される場合に使用できる oneof 型。
  • map 型。Key-Value ペアを定義に追加します。

proto2 では、メッセージ拡張機能でメッセージ外にフィールドを定義できます。たとえば、protobuf ライブラリの内部メッセージ スキーマを使用すると、カスタムの使用方法固有の拡張機能を拡張できます。

使用可能なオプションについては、proto2 または proto3 の言語ガイドをご覧ください。

オプションと項目タイプを設定したら、項目番号を割り当てます。フィールド番号は再利用または再利用できません。フィールドが誤って削除されないように、フィールド番号を予約する必要があります。

その他のデータ型のサポート

プロトコル バッファは、可変長エンコードと固定サイズの両方を使用する整数など、多くのスカラー値タイプをサポートします。また、メッセージ(フィールドに割り当てることができるデータ型)を定義することで、独自の複合データ型を作成することもできます。単純な値と複合値の型に加えて、いくつかの一般的な型が公開されています。

一般的な型

  • Duration は、固定の固定期間です(42 秒など)。
  • Timestamp は、タイムゾーンやカレンダーに依存しない時点です(例: 2017-01-15T01:30:15.01Z)。
  • Interval は、タイムゾーンやカレンダーに依存しない時間間隔です(例: 2017-01-15T01:30:15.01Z - 2017-01-16T02:30:15.01Z)。
  • Date は、2025-09-19 などの暦日全体です。
  • DayOfWeek は、月曜日など、曜日です。
  • TimeOfDay は、10:42:23 などの時刻です。
  • LatLng は緯度と経度の組み合わせです。たとえば、緯度は 37.386051、経度は -122.083855 です。
  • Money は、通貨タイプの金額です(例: 42 米ドル)。
  • PostalAddress は住所です(例: 1600 Amphitheatre Parkway Mountain View, CA 94043 USA)。
  • Color は RGBA 色空間の色です。
  • Month は、1 月です(4 月など)。

プロトコル バッファのオープンソース理念

プロトコル バッファは、Google 以外のデベロッパーが社内で得られるメリットと同じことを実現するため、2008 年にオープンソース化されました。Google は、内部要件に対応するためにこのような変更を定期的に行うことで、オープンソース コミュニティをサポートしています。Google では、外部デベロッパーからの一部の pull リクエストを受け付けていますが、機能リクエストや Google 固有のニーズに準拠していないバグ修正に優先順位を付けることはできません。

その他のリソース