Editions 的特性設定
本主題概述了已釋出的版本中包含的特性。後續版本的特性將新增到本主題中。我們會在新聞部分釋出新版本。
在新的模式定義內容中配置特性設定之前,請確保您瞭解使用它們的原因。避免在特性中出現“貨物崇拜”現象。
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 匯入時可用或不可用。使用此特性將減少冗餘符號,從而建立更小的二進位制檔案。
除了為整個檔案設定預設值之外,您還可以使用 local 和 export 關鍵字來設定每個欄位的行為。更多資訊請參閱export / local 關鍵字。
可用值
EXPORT_ALL:這是 2024 版本之前的預設值。所有訊息和列舉預設都會匯出。EXPORT_TOP_LEVEL:所有頂級符號預設匯出;巢狀符號預設本地。LOCAL_ALL:所有符號預設本地。STRICT:所有符號預設本地。巢狀型別不能匯出,除了message { enum {} reserved 0 to max; }的特殊情況。這將成為未來版本的預設設定。
適用於以下範圍: 檔案
添加於: 2024 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | EXPORT_TOP_LEVEL |
| 2023 | EXPORT_ALL |
| proto3 | EXPORT_ALL |
| proto2 | EXPORT_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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | STYLE2024 |
| 2023 | STYLE_LEGACY |
| proto3 | STYLE_LEGACY |
| proto2 | STYLE_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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | OPEN |
| 2023 | OPEN |
| proto3 | OPEN |
| proto2 | CLOSED |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | EXPLICIT |
| 2023 | EXPLICIT |
| proto3 | IMPLICIT* |
| proto2 | EXPLICIT |
* 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;
}
請注意,required 和 optional 標籤在版本中不再存在,因為相應的行為是使用 field_presence 特性明確設定的。
features.json_format
此特性設定了 JSON 解析和序列化的行為。
此特性不影響 proto3 檔案,因此本節沒有 proto3 檔案的前後對比。版本行為與 proto3 中的行為匹配。
可用值
ALLOW:執行時必須允許 JSON 解析和序列化。在 proto 級別應用檢查以確保存在明確的 JSON 對映。LEGACY_BEST_EFFORT:執行時盡力解析和序列化 JSON。允許某些 proto 導致執行時未指定的行為(例如多對一或一對多對映)。
適用於以下範圍: 檔案、訊息、列舉
添加於: 2023 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | ALLOW |
| 2023 | ALLOW |
| proto3 | ALLOW |
| proto2 | LEGACY_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訊息編碼 - 訊息型別與欄位定義在同一作用域內
- 欄位名與型別名完全小寫相同
可用值
適用於以下範圍: 檔案、欄位
添加於: 2023 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | LENGTH_PREFIXED |
| 2023 | LENGTH_PREFIXED |
| proto3 | LENGTH_PREFIXED |
| proto2 | LENGTH_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 記錄,其中包含每個元素串聯。EXPANDED:Repeated欄位每個值都用欄位號編碼。
適用於以下範圍: 檔案、欄位
添加於: 2023 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | PACKED |
| 2023 | PACKED |
| proto3 | PACKED |
| proto2 | EXPANDED |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | VERIFY |
| 2023 | VERIFY |
| proto3 | VERIFY |
| proto2 | NONE |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2023 | API_OPEN |
| 2024 | API_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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | true |
| 2023 | false |
| proto3 | false |
| proto2 | false |
注意: 不同模式元素上的特性設定具有不同的作用域。
features.(pb.java).large_enum
語言: Java
此特定語言特性允許您採用新功能來處理 Java 中的大型列舉,而不會導致編譯器錯誤。請注意,此特性複製了類似列舉的行為,但有一些顯著差異。例如,不支援 switch 語句。
可用值
true:Java 列舉將使用新功能。false:Java 列舉將繼續使用 Java 列舉。
適用於以下範圍: 檔案、列舉
添加於: 2024 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | false |
| 2023 | false |
| proto3 | false |
| proto2 | false |
注意: 不同模式元素上的特性設定具有不同的作用域。
features.(pb.cpp/pb.java).legacy_closed_enum
語言: C++、Java
此特性決定了具有開放列舉型別的欄位是否應表現得像封閉列舉。這使得版本能夠重現 proto2 和 proto3 中 Java 和 C++ 的不一致行為。
此特性不影響 proto3 檔案,因此本節沒有 proto3 檔案的前後對比。
可用值
true:無論enum_type設定如何,都將列舉視為封閉。false:遵循enum_type中的設定。
適用於以下範圍: 檔案、欄位
添加於: 2023 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | false |
| 2023 | false |
| proto3 | false |
| proto2 | true |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本之前的預設值 BarBaz 或 BarBazOuterClass,具體取決於是否存在衝突。
可用值
NO:不將生成的類巢狀在檔案類中。YES:將生成的類巢狀在檔案類中。- 舊版:巢狀行為由
java_multiple_files選項控制(參見 go/java-proto-names#immutable-api-message-names)。
適用於以下範圍: 訊息、列舉、服務
添加於: 2024 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | NO |
| 2023 | 舊版 |
| proto3 | 舊版 |
| proto2 | 舊版 |
注意: 不同模式元素上的特性設定具有不同的作用域。
features.(pb.cpp).string_type
語言: C++
此特性決定了生成的程式碼應如何處理字串欄位。它取代了 proto2 和 proto3 中的 ctype 選項,並提供了新的 string_type 特性。在 2023 版本中,您可以在欄位上指定 ctype 或 string_type,但不能同時指定。在 2024 版本中,ctype 選項已被移除。
可用值
VIEW:為欄位生成string_view訪問器。CORD:為欄位生成Cord訪問器。不支援擴充套件欄位。STRING:為欄位生成string訪問器。
適用於以下範圍: 檔案、欄位
添加於: 2023 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | VIEW |
| 2023 | STRING |
| proto3 | STRING |
| proto2 | STRING |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | DEFAULT |
| 2023 | DEFAULT |
| proto3 | DEFAULT |
| proto2 | DEFAULT |
注意: 不同模式元素上的特性設定具有不同的作用域。
以下程式碼示例展示了一個 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 版本
每個語法/版本的預設行為
| 語法/版本 | 預設 |
|---|---|
| 2024 | STRIP_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 版本及更高版本
- (C++)
ctype:刪除所有ctype選項例項,並設定features.(pb.cpp).string_type值。 - (C++ 和 Go)
weak:刪除弱匯入。改用import option。 - (Java)
java_multiple_files:刪除java_multiple_files,改用features.(pb.java).nest_in_file_class。