Editions 的特性設定

Protobuf 版本特性及其如何影響 Protobuf 行為。

本主題概述了已釋出的版本中包含的特性。後續版本的特性將新增到本主題中。我們會在新聞部分釋出新版本。

在新的模式定義內容中配置特性設定之前,請確保您瞭解使用它們的原因。避免在特性中出現“貨物崇拜”現象。

Prototiller

Prototiller 是一個命令列工具,用於在語法版本和版本之間更新 proto 模式配置檔案。它尚未釋出,但在本主題中被多次引用。

特性

以下各節包含了版本中可使用特性配置的所有行為。保留 proto2 或 proto3 行為展示瞭如何覆蓋預設行為,使您的 proto 定義檔案表現得像 proto2 或 proto3 檔案。有關版本和特性如何協同工作以設定行為的更多資訊,請參閱Protobuf 版本概述

特性設定適用於不同級別

檔案級: 這些設定適用於所有沒有覆蓋設定的元素(訊息、欄位、列舉等)。

非巢狀: 訊息、列舉和服務可以覆蓋檔案級別所做的設定。它們適用於其內部所有未被覆蓋的內容(訊息欄位、列舉值),但不適用於其他並行訊息和列舉。

巢狀: Oneof、訊息和列舉可以覆蓋它們巢狀的訊息中的設定。

最低級別: 欄位、擴充套件、列舉值、擴充套件範圍和方法是您可以覆蓋設定的最低級別。

以下每個部分都有一個註釋,說明該特性可以應用於哪個範圍。以下示例展示了一個模擬特性應用於每個範圍的情況

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

此特性允許設定訊息和列舉的預設可見性,使其在被其他 protos 匯入時可用或不可用。使用此特性將減少冗餘符號,從而建立更小的二進位制檔案。

除了為整個檔案設定預設值之外,您還可以使用 localexport 關鍵字來設定每個欄位的行為。更多資訊請參閱export / local 關鍵字

可用值

  • EXPORT_ALL:這是 2024 版本之前的預設值。所有訊息和列舉預設都會匯出。
  • EXPORT_TOP_LEVEL:所有頂級符號預設匯出;巢狀符號預設本地。
  • LOCAL_ALL:所有符號預設本地。
  • STRICT:所有符號預設本地。巢狀型別不能匯出,除了 message { enum {} reserved 0 to max; } 的特殊情況。這將成為未來版本的預設設定。

適用於以下範圍: 檔案

添加於: 2024 版本

每個語法/版本的預設行為

語法/版本預設
2024EXPORT_TOP_LEVEL
2023EXPORT_ALL
proto3EXPORT_ALL
proto2EXPORT_ALL

注意: 不同模式元素上的特性設定具有不同的作用域

以下示例展示瞭如何在您的 proto 模式定義檔案中的元素上應用該特性

// 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

此特性在 2024 版本中引入,它強制執行樣式指南中定義的嚴格命名樣式,以確保 protos 預設可往返,並提供一個特性值用於選擇不使用

可用值

  • STYLE2024:強制嚴格遵守命名樣式指南。
  • STYLE_LEGACY:應用 2024 版本之前的樣式指南執行級別。

適用於以下範圍: 檔案、擴充套件範圍、訊息、欄位、oneof、列舉、列舉值、服務、方法

添加於: 2024 版本

每個語法/版本的預設行為

語法/版本預設
2024STYLE2024
2023STYLE_LEGACY
proto3STYLE_LEGACY
proto2STYLE_LEGACY

注意: 不同模式元素上的特性設定具有不同的作用域

以下程式碼示例展示了一個 2023 版本檔案

2023 版本預設為 STYLE_LEGACY,因此不符合規範的欄位名是允許的

edition = "2023";

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

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: 開放列舉將超出範圍的值直接解析到其欄位中。

適用於以下範圍: 檔案、列舉

添加於: 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_* 函式。

適用於以下範圍: 檔案、欄位

添加於: 2023 版本

每個語法/版本的預設行為

語法/版本預設
2024EXPLICIT
2023EXPLICIT
proto3IMPLICIT*
proto2EXPLICIT

* proto3 是 IMPLICIT,除非該欄位具有 optional 標籤,在這種情況下,它的行為類似於 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;
}

請注意,requiredoptional 標籤在版本中不再存在,因為相應的行為是使用 field_presence 特性明確設定的。

features.json_format

此特性設定了 JSON 解析和序列化的行為。

此特性不影響 proto3 檔案,因此本節沒有 proto3 檔案的前後對比。版本行為與 proto3 中的行為匹配。

可用值

  • ALLOW:執行時必須允許 JSON 解析和序列化。在 proto 級別應用檢查以確保存在明確的 JSON 對映。
  • LEGACY_BEST_EFFORT:執行時盡力解析和序列化 JSON。允許某些 proto 導致執行時未指定的行為(例如多對一或一對多對映)。

適用於以下範圍: 檔案、訊息、列舉

添加於: 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:訊息型別欄位編碼為

適用於以下範圍: 檔案、欄位

添加於: 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 packed 選項在版本中遷移後的 repeated 欄位。

可用值

  • PACKED:原始型別的 Repeated 欄位編碼為單個 LEN 記錄,其中包含每個元素串聯。
  • EXPANDEDRepeated 欄位每個值都用欄位號編碼。

適用於以下範圍: 檔案、欄位

添加於: 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 的預設行為。

適用於以下範圍: 檔案、欄位

添加於: 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];
}

特定語言的特性

有些特性適用於特定語言,而不適用於其他語言中的相同 proto。使用這些特性需要您從該語言的執行時匯入相應的 *_features.proto 檔案。以下各節的示例展示了這些匯入。

features.(pb.go).api_level

語言: Go

api_level 特性允許您選擇 Go protobuf 外掛應為其生成程式碼的 API 版本。不透明 API 是 Go 程式語言的 Protocol Buffers 實現的最新版本。以前的版本現在稱為開放結構 API。請參閱Go Protobuf:釋出不透明 API 部落格文章以瞭解介紹。

可用值

  • API_OPEN:開放結構 API 生成的結構型別可以被直接訪問。
  • API_HYBRID:混合 API 是開放 API 和不透明 API 之間的一個過渡階段:混合 API 也包含訪問器方法(因此您可以更新程式碼),但仍然像以前一樣匯出結構欄位。沒有效能差異;此 API 級別僅有助於遷移。
  • API_OPAQUE:使用不透明 API,結構欄位被隱藏,不能再直接訪問。相反,新的訪問器方法允許獲取、設定或清除欄位。

適用於以下範圍: 訊息、檔案

添加於: 2023 版本

每個語法/版本的預設行為

語法/版本預設
2023API_OPEN
2024API_OPAQUE

注意: 不同模式元素上的特性設定具有不同的作用域

您可以從 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;

另請參閱:不透明 API:遷移

features.(pb.cpp).enum_name_uses_string_view

語言: C++

在 2024 版本之前,所有生成的列舉型別都提供了以下函式,用於從列舉值中獲取標籤,這在執行時構建 std::string 例項時會產生一些開銷

const std::string& Foo_Name(int);

2024 版本中的預設特性值將此簽名更改為返回 absl::string_view,以實現更好的儲存解耦和潛在的記憶體/CPU 節省。如果您尚未準備好遷移,可以覆蓋此設定以將其恢復到以前的行為。有關此主題的更多資訊,請參閱遷移指南中的string_view 返回型別

可用值

  • true:列舉為其值使用 string_view
  • false:列舉為其值使用 std::string

適用於以下範圍: 檔案、列舉

添加於: 2024 版本

每個語法/版本的預設行為

語法/版本預設
2024true
2023false
proto3false
proto2false

注意: 不同模式元素上的特性設定具有不同的作用域

features.(pb.java).large_enum

語言: Java

此特定語言特性允許您採用新功能來處理 Java 中的大型列舉,而不會導致編譯器錯誤。請注意,此特性複製了類似列舉的行為,但有一些顯著差異。例如,不支援 switch 語句。

可用值

  • true:Java 列舉將使用新功能。
  • false:Java 列舉將繼續使用 Java 列舉。

適用於以下範圍: 檔案、列舉

添加於: 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 中的設定。

適用於以下範圍: 檔案、欄位

添加於: 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/2023 版本中設定 java_multiple_files = true

預設的外部類名也已更新,預設情況下始終是駝峰式 .proto 檔名後跟 Proto(例如,foo/bar_baz.proto 變為 BarBazProto)。您仍然可以使用 java_outer_classname 檔案選項覆蓋此設定,並替換 2024 版本之前的預設值 BarBazBarBazOuterClass,具體取決於是否存在衝突。

可用值

  • NO:不將生成的類巢狀在檔案類中。
  • YES:將生成的類巢狀在檔案類中。
  • 舊版:巢狀行為由 java_multiple_files 選項控制(參見 go/java-proto-names#immutable-api-message-names)。

適用於以下範圍: 訊息、列舉、服務

添加於: 2024 版本

每個語法/版本的預設行為

語法/版本預設
2024NO
2023舊版
proto3舊版
proto2舊版

注意: 不同模式元素上的特性設定具有不同的作用域

features.(pb.cpp).string_type

語言: C++

此特性決定了生成的程式碼應如何處理字串欄位。它取代了 proto2 和 proto3 中的 ctype 選項,並提供了新的 string_type 特性。在 2023 版本中,您可以在欄位上指定 ctypestring_type,但不能同時指定。在 2024 版本中,ctype 選項已被移除。

可用值

  • VIEW:為欄位生成 string_view 訪問器。
  • CORD:為欄位生成 Cord 訪問器。不支援擴充套件欄位。
  • STRING:為欄位生成 string 訪問器。

適用於以下範圍: 檔案、欄位

添加於: 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

適用於以下範圍: 檔案、欄位

添加於: 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 程式碼現在將包含兩個字首!

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:從列舉值名稱中剝離列舉名稱字首。

適用於以下範圍: 檔案、列舉、列舉值

添加於: 2024 版本

每個語法/版本的預設行為

語法/版本預設
2024STRIP_ENUM_PREFIX_KEEP

注意: 不同模式元素上的特性設定具有不同的作用域

您可以在 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 檔案所做的更改,以使基於 2023 版本的 proto 表現得像 proto2 或 proto3 檔案。

在檔案級別進行這些更改後,您將獲得 proto2 或 proto3 的預設值。您可以在較低級別(訊息級別、欄位級別)進行覆蓋,以考慮其他行為差異(例如必需、proto3 可選),或者如果您希望您的定義只大部分像 proto2 或 proto3。

除非有特殊原因,否則我們建議使用 Prototiller。要手動應用所有這些設定而不是使用 Prototiller,請將以下各節的內容新增到您的 .proto 檔案頂部。

Proto2 行為

以下顯示了使用 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 行為

以下顯示了使用 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 版本

以下顯示了使用 2024 版本複製 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,您需要手動進行的更改。

在上一節中顯示的檔案級預設設定在大多數情況下設定了預設行為,但也有一些例外。

2023 版本及更高版本

  • optional:刪除所有 optional 標籤例項,如果檔案預設值為 IMPLICIT,則將features.field_presence更改為 EXPLICIT
  • 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 檔案,當您不希望在Proto2 行為中設定的 EXPANDED 行為時,請刪除 packed 欄位選項,並在欄位級別新增 [features.repeated_field_encoding=PACKED]。對於轉換為版本格式的 proto3 檔案,當您不希望預設的 proto3 行為時,請在欄位級別新增 [features.repeated_field_encoding=EXPANDED]

2024 版本及更高版本