エディションの機能設定

Protobuf Editionsの機能と、それがProtobufの動作にどのように影響するか。

このトピックでは、リリースされたエディションバージョンに含まれる機能の概要を説明します。今後のエディションの機能は、このトピックに追加されます。新しいエディションはニュースセクションで発表しています。

新しいスキーマ定義コンテンツで機能設定を構成する前に、なぜそれらを使用するのかを理解していることを確認してください。機能のカーゴカルトを避けてください。

Prototiller

Prototillerは、プロトスキーマ構成ファイルを構文バージョンとエディション間で更新するコマンドラインツールです。まだリリースされていませんが、このトピック全体で参照されています。

機能

以下のセクションには、エディションの機能を使用して構成できるすべての動作が含まれています。proto2またはproto3の動作を維持するでは、デフォルトの動作をオーバーライドして、プロト定義ファイルがproto2またはproto3ファイルのように動作するようにする方法を示しています。エディションと機能が連携して動作を設定する方法の詳細については、Protobuf Editionsの概要を参照してください。

機能設定は異なるレベルで適用されます

ファイルレベル: これらの設定は、オーバーライド設定がないすべての要素(メッセージ、フィールド、列挙型など)に適用されます。

非ネスト: メッセージ、列挙型、サービスは、ファイルレベルで行われた設定をオーバーライドできます。それらは、オーバーライドされていない内部のすべて(メッセージフィールド、列挙値)に適用されますが、他の並列のメッセージや列挙型には適用されません。

ネスト: Oneofs、メッセージ、列挙型は、ネストされているメッセージの設定をオーバーライドできます。

最下位レベル: フィールド、拡張機能、列挙値、拡張範囲、メソッドは、設定をオーバーライドできる最下位レベルです。

以下の各セクションには、その機能が適用できるスコープを示すコメントがあります。次のサンプルは、各スコープに適用されるモック機能を示しています。

edition = "2024";

// File-level scope definition
option features.bar = BAZ;

enum Foo {
  // Enum (non-nested scope) definition
  option features.bar = QUX;

  A = 1;
  B = 2;
}

message Corge {
  // Message (non-nested scope) definition
  option features.bar = QUUX;

  message Garply {
    // Message (nested scope) definition
    option features.bar = WALDO;
    string id = 1;
  }

  // Field (lowest-level scope) definition
  Foo A = 1 [features.bar = GRAULT];
}

この例では、最下位レベルのスコープ機能定義の「GRAULT」設定が、非ネストスコープの「QUUX」設定をオーバーライドします。また、Garplyメッセージ内では、「WALDO」が「QUUX」をオーバーライドします。

features.default_symbol_visibility

この機能により、メッセージと列挙型のデフォルトの可視性を設定できるようになり、他のプロトによってインポートされたときに利用可能または利用不可能になります。この機能を使用すると、不要なシンボルが減り、バイナリサイズが小さくなります。

ファイル全体のデフォルト設定に加えて、localおよびexportキーワードを使用してフィールドごとの動作を設定できます。詳細については、export / local キーワードを参照してください。

利用可能な値

  • EXPORT_ALL: これはEdition 2024以前のデフォルトです。すべてのメッセージと列挙型はデフォルトでエクスポートされます。
  • EXPORT_TOP_LEVEL: すべてのトップレベルシンボルはデフォルトでエクスポートされます。ネストされたシンボルはデフォルトでローカルになります。
  • LOCAL_ALL: すべてのシンボルはデフォルトでローカルになります。
  • STRICT: すべてのシンボルはデフォルトでローカルです。ネストされた型は、message { enum {} reserved 0 to max; }の特殊な例外を除いて、エクスポートできません。これは将来のエディションでデフォルトになります。

以下のスコープに適用可能: Enum、Message

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024EXPORT_TOP_LEVEL
2023EXPORT_ALL
proto3EXPORT_ALL
proto2EXPORT_ALL

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のサンプルは、プロトスキーマ定義ファイルの要素に機能を適用する方法を示しています。

// foo.proto
edition = "2024";

// Symbol visibility defaults to EXPORT_TOP_LEVEL. Setting
// default_symbol_visibility overrides these defaults
option features.default_symbol_visibility = LOCAL_ALL;

// Top-level symbols are exported by default in Edition 2024; applying the local
// keyword overrides this
export message LocalMessage {
  int32 baz = 1;
  // Nested symbols are local by default in Edition 2024; applying the export
  // keyword overrides this
  enum ExportedNestedEnum {
    UNKNOWN_EXPORTED_NESTED_ENUM_VALUE = 0;
  }
}

// bar.proto
edition = "2024";

import "foo.proto";

message ImportedMessage {
  // The following is valid because the imported message explicitly overrides
  // the visibility setting in foo.proto
  LocalMessage bar = 1;

  // The following is not valid because default_symbol_visibility is set to
  // `LOCAL_ALL`
  // LocalMessage.ExportedNestedEnum qux = 2;
}

features.enforce_naming_style

Edition 2024で導入されたこの機能は、スタイルガイドで定義されている厳密な命名スタイルを強制し、プロトがデフォルトでラウンドトリップ可能であることを保証します。機能値でオプトアウトすることもできます。

利用可能な値

  • STYLE2024: 命名に関するスタイルガイドへの厳密な準拠を強制します。
  • STYLE_LEGACY: Edition 2024以前のスタイルガイド準拠レベルを適用します。

以下のスコープに適用可能: ファイル

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024STYLE2024
2023STYLE_LEGACY
proto3STYLE_LEGACY
proto2STYLE_LEGACY

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはEdition 2023ファイルを示しています。

Edition 2023はSTYLE_LEGACYがデフォルトであるため、非準拠のフィールド名でも問題ありません。

edition = "2023";

message Foo {
  // A non-conforming field name is not a problem
  int64 bar_1 = 1;
}

Edition 2024はSTYLE2024がデフォルトであるため、非準拠のフィールド名を維持するにはオーバーライドが必要です。

edition = "2024";

// To keep the non-conformant field name, override the STYLE2024 setting
option features.enforce_naming_style = "STYLE_LEGACY";

message Foo {
  int64 bar_1 = 1;
}

features.enum_type

この機能は、定義されたセットに含まれていない列挙値の処理方法を設定します。オープン列挙型とクローズ列挙型の詳細については、列挙型の動作を参照してください。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。

利用可能な値

  • CLOSED: クローズ列挙型は、範囲外の列挙値を不明なフィールドセットに保存します。
  • OPEN: オープン列挙型は、範囲外の値をフィールドに直接解析します。

以下のスコープに適用可能: ファイル、列挙型

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024OPEN
2023OPEN
proto3OPEN
proto2CLOSED

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

enum Foo {
  A = 2;
  B = 4;
  C = 6;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

enum Foo {
  // Setting the enum_type feature overrides the default OPEN enum
  option features.enum_type = CLOSED;
  A = 2;
  B = 4;
  C = 6;
}

features.field_presence

この機能は、フィールドの存在、つまりProtobufフィールドが値を持つかどうかの追跡に関する動作を設定します。

利用可能な値

  • LEGACY_REQUIRED: フィールドは解析とシリアル化に必須です。明示的に設定された値は、ワイヤにシリアル化されます(デフォルト値と同じ場合でも)。
  • EXPLICIT: フィールドには明示的な存在追跡があります。明示的に設定された値は、ワイヤにシリアル化されます(デフォルト値と同じ場合でも)。単一のプリミティブフィールドの場合、EXPLICITに設定されたフィールドに対してhas_*関数が生成されます。
  • IMPLICIT: フィールドには存在追跡がありません。デフォルト値は、ワイヤにシリアル化されません(明示的に設定されていても)。IMPLICITに設定されたフィールドに対してhas_*関数は生成されません。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024EXPLICIT
2023EXPLICIT
proto3IMPLICIT*
proto2EXPLICIT

* proto3は、フィールドにoptionalラベルがある場合を除いてIMPLICITです。その場合、EXPLICITのように動作します。詳細については、Proto3 APIでの存在を参照してください。

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message Foo {
  required int32 x = 1;
  optional int32 y = 2;
  repeated int32 z = 3;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

message Foo {
  // Setting the field_presence feature retains the proto2 required behavior
  int32 x = 1 [features.field_presence = LEGACY_REQUIRED];
  int32 y = 2;
  repeated int32 z = 3;
}

以下はproto3ファイルを示しています。

syntax = "proto3";

message Bar {
  int32 x = 1;
  optional int32 y = 2;
  repeated int32 z = 3;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";
// Setting the file-level field_presence feature matches the proto3 implicit default
option features.field_presence = IMPLICIT;

message Bar {
  int32 x = 1;
  // Setting the field_presence here retains the explicit state that the proto3
  // field has because of the optional syntax
  int32 y = 2 [features.field_presence = EXPLICIT];
  repeated int32 z = 3;
}

対応する動作がfield_presence機能で明示的に設定されるため、Editionsではrequiredおよびoptionalラベルは存在しないことに注意してください。

features.json_format

この機能は、JSONの解析とシリアル化の動作を設定します。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。Editionsの動作はproto3の動作と一致します。

利用可能な値

  • ALLOW: ランタイムはJSONの解析とシリアル化を許可する必要があります。JSONへの明確なマッピングがあることを確認するために、プロトレベルでチェックが適用されます。
  • LEGACY_BEST_EFFORT: ランタイムはJSONの解析とシリアル化を最大限に行います。ランタイムで不特定の動作を引き起こす可能性のある特定のプロト(多対1または1対多のマッピングなど)が許可されます。

以下のスコープに適用可能: ファイル、メッセージ、列挙型

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024ALLOW
2023ALLOW
proto3ALLOW
proto2LEGACY_BEST_EFFORT

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message Foo {
  // Warning only
  string bar = 1;
  string bar_ = 2;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";
option features.json_format = LEGACY_BEST_EFFORT;

message Foo {
  string bar = 1;
  string bar_ = 2;
}

features.message_encoding

この機能は、シリアル化時のフィールドのエンコーディング動作を設定します。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。

言語によっては、「グループライク」なフィールドが生成されたコードやテキスト形式で予期しない大文字小文字を持つ場合がありますが、これはproto2との下位互換性を提供するためです。メッセージフィールドは、次のすべての条件が満たされている場合に「グループライク」になります。

  • DELIMITEDメッセージエンコーディングが指定されている
  • メッセージ型がフィールドと同じスコープで定義されている
  • フィールド名が型名の小文字とまったく同じ

利用可能な値

  • LENGTH_PREFIXED: フィールドはメッセージ構造で説明されているLENワイヤタイプを使用してエンコードされます。
  • DELIMITED: メッセージ型のフィールドはグループとしてエンコードされます。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024LENGTH_PREFIXED
2023LENGTH_PREFIXED
proto3LENGTH_PREFIXED
proto2LENGTH_PREFIXED

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message Foo {
  group Bar = 1 {
    optional int32 x = 1;
    repeated int32 y = 2;
  }
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

message Foo {
  message Bar {
    int32 x = 1;
    repeated int32 y = 2;
  }
  Bar bar = 1 [features.message_encoding = DELIMITED];
}

features.repeated_field_encoding

この機能は、proto2/proto3のrepeatedフィールドのpackedオプションがEditionsで移行されたものです。

利用可能な値

  • PACKED: プリミティブ型のRepeatedフィールドは、各要素を連結した単一のLENレコードとしてエンコードされます。
  • EXPANDED: Repeatedフィールドは、各値のフィールド番号でそれぞれエンコードされます。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024PACKED
2023PACKED
proto3PACKED
proto2EXPANDED

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message Foo {
  repeated int32 bar = 6 [packed=true];
  repeated int32 baz = 7;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";
option features.repeated_field_encoding = EXPANDED;

message Foo {
  repeated int32 bar = 6 [features.repeated_field_encoding=PACKED];
  repeated int32 baz = 7;
}

以下はproto3ファイルを示しています。

syntax = "proto3";

message Foo {
  repeated int32 bar = 6;
  repeated int32 baz = 7 [packed=false];
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

message Foo {
  repeated int32 bar = 6;
  repeated int32 baz = 7 [features.repeated_field_encoding=EXPANDED];
}

features.utf8_validation

この機能は、文字列の検証方法を設定します。言語固有のutf8_validation機能がそれをオーバーライドしない限り、すべての言語に適用されます。Java言語固有の機能については、features.(pb.java).utf8_validationを参照してください。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。

利用可能な値

  • VERIFY: ランタイムはUTF-8を検証する必要があります。これはデフォルトのproto3の動作です。
  • NONE: フィールドは、ワイヤ上で検証されていないbytesフィールドのように動作します。パーサーは、無効な文字を置換するなど、このタイプのフィールドを予測できない方法で処理する可能性があります。これはデフォルトのproto2の動作です。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024VERIFY
2023VERIFY
proto3VERIFY
proto2NONE

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message MyMessage {
  string foo = 1;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

message MyMessage {
  string foo = 1 [features.utf8_validation = NONE];
}

言語固有の機能

一部の機能は特定の言語に適用され、他の言語の同じプロトには適用されません。これらの機能を使用するには、その言語のランタイムから対応する*_features.protoファイルをインポートする必要があります。以下のセクションの例は、これらのインポートを示しています。

features.(pb.go).api_level

言語: Go

api_level機能を使用すると、Go protobufプラグインがコードを生成するAPIバージョンを選択できます。Opaque APIは、Goプログラミング言語用のProtocol Buffers実装の最新バージョンです。以前のバージョンは現在Open Struct APIと呼ばれています。導入については、Go Protobuf: Releasing the Opaque APIブログ投稿を参照してください。

利用可能な値

  • API_OPEN: Open Struct APIは、直接アクセス可能な構造体型を生成します。
  • API_HYBRID: HybridはOpenとOpaqueの中間段階です。Hybrid APIにはアクセサメソッドも含まれています(コードを更新できます)が、以前と同様に構造体フィールドをエクスポートします。パフォーマンスの違いはありません。このAPIレベルは移行に役立つだけです。
  • API_OPAQUE: Opaque APIでは、構造体フィールドは隠され、直接アクセスできなくなります。代わりに、新しいアクセサメソッドにより、フィールドの取得、設定、またはクリアが可能になります。

以下のスコープに適用可能: メッセージ、ファイル

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2023API_OPEN
2024API_OPAQUE

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

Edition 2023以降でapi_level機能を設定できます。

edition = "2023";

import "google/protobuf/go_features.proto";

// Remove this line after migrating the code to the Opaque API.
option features.(pb.go).api_level = API_HYBRID;

関連項目: Opaque API: 移行

features.(pb.cpp).enum_name_uses_string_view

言語: C++

Edition 2024より前は、生成されたすべての列挙型は、列挙値からラベルを取得するために次の関数を提供していました。これは、実行時にstd::stringインスタンスを構築するためのオーバーヘッドがありました。

const std::string& Foo_Name(int);

Edition 2024のデフォルトの機能値は、このシグネチャをabsl::string_viewを返すように変更し、ストレージの結合度を改善し、メモリ/CPUの節約の可能性を広げます。まだ移行する準備ができていない場合は、これをオーバーライドして以前の動作に戻すことができます。このトピックの詳細については、移行ガイドのstring_view戻り値の型を参照してください。

利用可能な値

  • true: 列挙型はその値にstring_viewを使用します。
  • false: 列挙型はその値にstd::stringを使用します。

以下のスコープに適用可能: Enum、ファイル

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024true
2023false
proto3false
proto2false

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

features.(pb.java).large_enum

言語: Java

この言語固有の機能により、Javaで大きな列挙型をコンパイラエラーなしで処理する新しい機能を採用できます。この機能は列挙型のような動作を複製しますが、いくつかの顕著な違いがあることに注意してください。たとえば、switch文はサポートされていません。

利用可能な値

  • true: Javaの列挙型は新しい機能を使用します。
  • false: Javaの列挙型は引き続きJavaの列挙型を使用します。

以下のスコープに適用可能: Enum

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024false
2023false
proto3false
proto2false

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

features.(pb.cpp/pb.java).legacy_closed_enum

言語: C++、Java

この機能は、オープンな列挙型を持つフィールドが、クローズな列挙型であるかのように動作するかどうかを決定します。これにより、エディションはproto2およびproto3のJavaおよびC++における非準拠の動作を再現できます。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。

利用可能な値

  • true: enum_typeに関係なく、列挙型をクローズとして扱います。
  • false: enum_typeに設定されているものを尊重します。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024false
2023false
proto3false
proto2true

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

import "myproject/proto3file.proto";

message Msg {
  myproject.proto3file.Proto3Enum name = 1;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

import "myproject/proto3file.proto";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

message Msg {
  myproject.proto3file.Proto3Enum name = 1 [
    features.(pb.cpp).legacy_closed_enum = true,
    features.(pb.java).legacy_closed_enum = true
  ];
}

features.(pb.java).nest_in_file_class

言語: Java

この機能は、Javaジェネレータが生成されたクラスをJava生成ファイルクラスにネストするかどうかを制御します。このオプションをNOに設定することは、proto2/proto3/Edition 2023でjava_multiple_files = trueを設定することと同じです。

デフォルトのアウタークラス名も、デフォルトで常にキャメルケースの.protoファイル名にProtoを接尾辞として追加したものに更新されます(例:foo/bar_baz.protoBarBazProtoになります)。競合の有無に応じて、java_outer_classnameファイルオプションを使用してこれをオーバーライドし、Edition 2024以前のデフォルトであるBarBazまたはBarBazOuterClassを置き換えることができます。

利用可能な値

  • NO: 生成されたクラスをファイルクラスにネストしません。
  • YES: 生成されたクラスをファイルクラスにネストします。
  • Legacy: java_multiple_filesオプションが設定されているときに使用される内部値。

以下のスコープに適用可能: メッセージ、列挙型、サービス

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024NO
2023LEGACY
proto3LEGACY
proto2LEGACY

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

features.(pb.cpp).string_type

言語: C++

この機能は、生成されたコードが文字列フィールドをどのように扱うかを決定します。これはproto2およびproto3のctypeオプションを置き換え、新しいstring_type機能を提供します。Edition 2023では、フィールドにctypeまたはstring_typeのいずれかを指定できますが、両方を指定することはできません。Edition 2024では、ctypeオプションは削除されます。

利用可能な値

  • VIEW: フィールドにstring_viewアクセサを生成します。
  • CORD: フィールドにCordアクセサを生成します。拡張フィールドではサポートされていません。
  • STRING: フィールドにstringアクセサを生成します。

以下のスコープに適用可能: ファイル、フィールド

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024VIEW
2023STRING
proto3STRING
proto2STRING

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

message Foo {
  optional string bar = 6;
  optional string baz = 7 [ctype = CORD];
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

import "google/protobuf/cpp_features.proto";

message Foo {
  string bar = 6 [features.(pb.cpp).string_type = STRING];
  string baz = 7 [features.(pb.cpp).string_type = CORD];
}

以下はproto3ファイルを示しています。

syntax = "proto3"

message Foo {
  string bar = 6;
  string baz = 7 [ctype = CORD];
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

import "google/protobuf/cpp_features.proto";

message Foo {
  string bar = 6 [features.(pb.cpp).string_type = STRING];
  string baz = 7 [features.(pb.cpp).string_type = CORD];
}

features.(pb.java).utf8_validation

言語: Java

この言語固有の機能により、Javaのみ、フィールドレベルでファイルレベルの設定をオーバーライドできます。

この機能はproto3ファイルには影響しないため、このセクションにはproto3ファイルの前後の例はありません。

利用可能な値

  • DEFAULT: 動作はfeatures.utf8_validationで設定されたものと一致します。
  • VERIFY: ファイルレベルのfeatures.utf8_validation設定をオーバーライドし、JavaのみVERIFYに強制します。

以下のスコープに適用可能: フィールド、ファイル

追加日: Edition 2023

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024DEFAULT
2023DEFAULT
proto3DEFAULT
proto2DEFAULT

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

以下のコードサンプルはproto2ファイルを示しています。

syntax = "proto2";

option java_string_check_utf8=true;

message MyMessage {
  string foo = 1;
  string bar = 2;
}

Prototillerを実行すると、同等のコードは次のようになる可能性があります。

edition = "2024";

import "google/protobuf/java_features.proto";

option features.utf8_validation = NONE;
option features.(pb.java).utf8_validation = VERIFY;
message MyMessage {
  string foo = 1;
  string bar = 2;
}

features.(pb.go).strip_enum_prefix

言語: Go

列挙値はそれらを含む列挙名によってスコープ化されないため、すべての値に列挙名でプレフィックスを付けることをお勧めします

edition = "2024";

enum Strip {
  STRIP_ZERO = 0;
  STRIP_ONE = 1;
}

しかし、生成されたGoコードには2つのプレフィックスが含まれることになります!

type Strip int32

const (
    Strip_STRIP_ZERO Strip = 0
    Strip_STRIP_ONE  Strip = 1
)

言語固有のstrip_enum_prefix機能は、Goコードジェネレータが繰り返しプレフィックスを削除するかどうかを決定します。

利用可能な値

  • STRIP_ENUM_PREFIX_KEEP: 繰り返しであっても、名前をそのまま保持します。
  • STRIP_ENUM_PREFIX_GENERATE_BOTH: 完全な名前と削除された名前の両方を生成します(Goコードの移行を支援するため)。
  • STRIP_ENUM_PREFIX_STRIP: 列挙値名から列挙名プレフィックスを削除します。

以下のスコープに適用可能: Enum、ファイル

追加日: Edition 2024

構文/エディションごとのデフォルト動作

構文/エディションデフォルト
2024STRIP_ENUM_PREFIX_KEEP

注: 異なるスキーマ要素の機能設定は異なるスコープを持ちます。

Edition 2024(またはそれ以降)の.protoファイルでstrip_enum_prefix機能を設定できます。

edition = "2024";

import "google/protobuf/go_features.proto";

option features.(pb.go).strip_enum_prefix = STRIP_ENUM_PREFIX_STRIP;

enum Strip {
  STRIP_ZERO = 0;
  STRIP_ONE = 1;
}

生成されたGoコードは、STRIPプレフィックスを削除します。

type Strip int32

const (
    Strip_ZERO Strip = 0
    Strip_ONE  Strip = 1
)

エディション2023でproto2またはproto3の動作を維持する

エディション形式に移行したいが、生成されたコードの動作の更新に対処したくない場合があります。このセクションでは、Prototillerツールが.protoファイルに対して行う変更を示し、Edition 2023ベースのプロトがproto2またはproto3ファイルのように動作するようにします。

これらの変更がファイルレベルで行われると、proto2またはproto3のデフォルトが適用されます。下位レベル(メッセージレベル、フィールドレベル)でオーバーライドして、追加の動作の違い(必須、proto3オプションなど)を考慮したり、定義をほとんどproto2またはproto3のようにしたい場合に適用したりできます。

特定の理由がない限り、Prototillerを使用することをお勧めします。Prototillerを使用せずにこれらすべてを手動で適用するには、以下のセクションのコンテンツを.protoファイルの先頭に追加します。

Proto2の動作

以下は、Edition 2023でproto2の動作を再現するための設定を示しています。

edition = "2023";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

option features.field_presence = EXPLICIT;
option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED;
option features.json_format = LEGACY_BEST_EFFORT;
option features.utf8_validation = NONE;
option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.java).legacy_closed_enum = true;

Proto3の動作

以下は、Edition 2023でproto3の動作を再現するための設定を示しています。

edition = "2023";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

option features.field_presence = IMPLICIT;
option features.enum_type = OPEN;
// `packed=false` needs to be transformed to field-level repeated_field_encoding
// features in Editions syntax
option features.json_format = ALLOW;
option features.utf8_validation = VERIFY;
option features.(pb.cpp).legacy_closed_enum = false;
option features.(pb.java).legacy_closed_enum = false;

エディション2023から2024へ

以下は、Edition 2024でEdition 2023の動作を再現するための設定を示しています。

// foo/bar_baz.proto
edition = "2024";

import option "third_party/protobuf/cpp_features.proto";
import option "third_party/java/protobuf/java_features.proto";
import option "third_party/golang/protobuf/v2/src/google/protobuf/go_features.proto";

// If previously relying on edition 2023 default java_outer_classname.
option java_outer_classname = "BarBaz" // or BarBazOuterClass

option features.(pb.cpp).string_type = STRING;
option features.enforce_naming_style = STYLE_LEGACY;
option features.default_symbol_visibility = EXPORT_ALL;
option features.(pb.cpp).enum_name_uses_string_view = false;
option features.(pb.go).api_level = API_OPEN;

message MyMessage {
  option features.(pb.java).nest_in_file_class = YES;
}

注意点と例外

このセクションでは、Prototillerを使用しない場合に手動で行う必要のある変更を示します。

前のセクションで示したファイルレベルのデフォルトを設定することで、ほとんどの場合にデフォルトの動作が設定されますが、いくつかの例外があります。

Edition 2023以降

  • optional: optionalラベルのすべてのインスタンスを削除し、ファイルデフォルトがIMPLICITの場合はfeatures.field_presenceEXPLICITに変更します。
  • required: requiredラベルのすべてのインスタンスを削除し、フィールドレベルでfeatures.field_presence=LEGACY_REQUIREDオプションを追加します。
  • groups: groupsを個別のメッセージに展開し、フィールドレベルでfeatures.message_encoding = DELIMITEDオプションを追加します。詳細については、features.message_encodingを参照してください。
  • java_string_check_utf8: このファイルオプションを削除し、features.(pb.java).utf8_validationに置き換えます。言語固有の機能で説明されているように、Java機能をインポートする必要があります。
  • packed: エディション形式に変換されたproto2ファイルの場合、packedフィールドオプションを削除し、Proto2の動作で設定したEXPANDED動作が不要な場合はフィールドレベルで[features.repeated_field_encoding=PACKED]を追加します。エディション形式に変換されたproto3ファイルの場合、デフォルトのproto3動作が不要な場合はフィールドレベルで[features.repeated_field_encoding=EXPANDED]を追加します。

Edition 2024以降