Proto2 vs Proto3: 主な違い

proto2とproto3の構文の違いを比較:required/optionalフィールド、デフォルト値、enum、拡張機能、バージョン間の移行戦略。

Advanced Features

詳細な説明

Proto2 vs Proto3の比較

Proto3はいくつかのproto2機能を削除しデフォルトの動作を変更することで、protobuf言語を簡素化しました。違いの理解は、レガシースキーマの作業やバージョン間の移行に不可欠です。

// Proto2構文
syntax = "proto2";

message UserV2 {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
  optional int32 age = 4 [default = 0];
  repeated string tags = 5;

  extensions 100 to 199;
}

// Proto3構文
// syntax = "proto3";
//
// message UserV3 {
//   int32 id = 1;
//   string name = 2;
//   string email = 3;
//   optional int32 age = 4;
//   repeated string tags = 5;
// }

機能比較

機能 Proto2 Proto3
フィールドプレゼンス requiredoptional、暗黙 暗黙(すべてoptional)、明示的optionalキーワード
デフォルト値 カスタムデフォルト可 固定デフォルトのみ(0、false、"")
requiredキーワード サポート 削除(有害と判断)
不明フィールド デフォルトで破棄 デフォルトで保持
Enumゼロ値 必須でない ゼロ値必須
拡張機能 サポート 削除(代わりにAnyを使用)
グループ サポート(非推奨) 削除
Mapフィールド 利用不可 追加
JSONマッピング 基本 完全な標準マッピング

requiredが削除された理由

proto2のrequiredキーワードは後方互換性バグの最大の原因として特定されました。フィールドがrequiredとマークされると、既存のすべてのパーサーを壊さずに削除することは不可能です。proto3はすべてのフィールドをoptionalとして扱い、スキーマの進化をより安全にします。

Proto3のフィールドプレゼンス

proto3では、スカラーフィールドは明示的に設定されたかどうかを追跡しません。値が0のフィールドは「ゼロに設定」または「まったく設定されていない」のいずれかの可能性があります。これらのケースを区別するには:

  • ラッパー型を使用(google.protobuf.Int32Value
  • optionalキーワードを使用(proto3.15+で再追加)
  • ブーリアンコンパニオンフィールドを使用(例: bool has_age = 5;

移行戦略

proto2からproto3に移行する際:

  1. すべてのrequiredラベルを削除
  2. カスタムdefault値を削除
  3. extensionsを削除(google.protobuf.Anyまたはoneofで置換)
  4. すべてのenumにゼロ値があることを確認
  5. 既存のシリアライズデータでテストして互換性を検証

ユースケース

新しいプロジェクトでどのprotobufバージョンを使用するかの決定、レガシーproto2スキーマのproto3への移行、またはバージョンによって決定される特定のprotobufパターンをコードベースが使用する理由の理解。

試してみる — Protobuf Definition Parser

フルツールを開く