Editions 的特性设置

Protobuf 版本的功能以及它们如何影响 protobuf 的行为。

本主题概述了已发布版本中包含的功能。后续版本的功能将被添加到此主题中。我们会在“新闻”部分宣布新版本。

在新的 schema 定义内容中配置功能设置之前,请确保您理解使用它们的原因。避免在功能上盲目跟风

Prototiller

Prototiller 是一个命令行工具,用于在不同语法版本和版本之间更新 proto schema 配置文件。它尚未发布,但在本主题中多处被引用。

功能

以下各节包含了所有可通过版本中的功能进行配置的行为。保留 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];
}

«««< HEAD 在此示例中,最低级别作用域功能定义中的设置“GRAULT"覆盖了非嵌套作用域的“QUUX”设置。在 Garply 消息内部,“WALDO”覆盖了“QUUX”。

«««< HEAD

features.default_symbol_visibility

此功能允许设置消息和枚举的默认可见性,使其在被其他 proto 文件导入时可用或不可用。使用此功能将减少无效符号,以创建更小的二进制文件。

除了为整个文件设置默认值外,您还可以使用 localexport 关键字来设置每个字段的行为。更多相关信息请阅读export / local 关键字

可用值

  • EXPORT_ALL:这是 2024 版本之前的默认值。所有消息和枚举默认都被导出。
  • EXPORT_TOP_LEVEL:所有顶层符号默认为导出;嵌套符号默认为本地。
  • LOCAL_ALL:所有符号默认为本地。
  • STRICT:所有符号默认为本地。嵌套类型不能被导出,除了一个特殊情况,即消息 { enum {} reserved 1 to max; }。这是推荐给新 proto 文件的设置。

适用于以下作用域:枚举、消息

添加于:2024 版本

各语法/版本的默认行为

语法/版本默认值
2024EXPORT_TOP_LEVEL
2023EXPORT_ALL
proto3EXPORT_ALL
proto2EXPORT_ALL

注意:不同 schema 元素上的功能设置具有不同的作用域

以下示例展示了如何将该功能应用于您的 proto schema 定义文件中的元素

// 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 版本中引入,用于强制执行风格指南中定义的严格命名风格,以确保 proto 文件默认是可往返转换的,并提供一个功能值来选择退出

可用值

  • STYLE2024:强制严格遵守命名风格指南。
  • STYLE_LEGACY:应用 2024 版本之前的风格指南强制级别。

适用于以下作用域:文件

添加于 2024

各语法/版本的默认行为

语法/版本默认值
2024STYLE2024
2023STYLE_LEGACY
proto3STYLE_LEGACY
proto2STYLE_LEGACY

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 2023 版本的文件

2023 版本默认为 STYLE_LEGACY,所以不符合规范的字段名是可以接受的

edition = "2023";

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

2025 版本默认为 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;
}

||||||| dcf50a2 的父版本 (本文档更改包括以下内容:) 在此示例中,字段作用域功能定义中的设置 GRAULT 覆盖了消息作用域的 QUUX 设置。

在此示例中,最低级别作用域功能定义中的设置“GRAULT"覆盖了非嵌套作用域的“QUUX”设置。在 Garply 消息内部,“WALDO”覆盖了“QUUX”。

dcf50a2 (本文档更改包括以下内容:)

||||||| 81fd217 的父版本 (本文档更改包括以下内容:)

features.default_symbol_visibility

此功能允许设置消息和枚举的默认可见性,使其在被其他 proto 文件导入时可用或不可用。使用此功能将减少无效符号,以创建更小的二进制文件。

除了为整个文件设置默认值外,您还可以使用 localexport 关键字来设置每个字段的行为。更多相关信息请阅读export / local 关键字

可用值

  • EXPORT_ALL:这是 2024 版本之前的默认值。所有消息和枚举默认都被导出。
  • EXPORT_TOP_LEVEL:所有顶层符号默认为导出;嵌套符号默认为本地。
  • LOCAL_ALL:所有符号默认为本地。
  • STRICT:所有符号默认为本地。嵌套类型不能被导出,除了一个特殊情况,即消息 { enum {} reserved 1 to max; }。这是推荐给新 proto 文件的设置。

适用于以下作用域:枚举、消息

添加于:2024 版本

各语法/版本的默认行为

语法/版本默认值
2024EXPORT_TOP_LEVEL
2023EXPORT_ALL
proto3EXPORT_ALL
proto2EXPORT_ALL

注意:不同 schema 元素上的功能设置具有不同的作用域

以下示例展示了如何将该功能应用于您的 proto schema 定义文件中的元素

// 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 版本中引入,用于强制执行风格指南中定义的严格命名风格,以确保 proto 文件默认是可往返转换的,并提供一个功能值来选择退出

可用值

  • STYLE2024:强制严格遵守命名风格指南。
  • STYLE_LEGACY:应用 2024 版本之前的风格指南强制级别。

适用于以下作用域:文件

添加于 2024

各语法/版本的默认行为

语法/版本默认值
2024STYLE2024
2023STYLE_LEGACY
proto3STYLE_LEGACY
proto2STYLE_LEGACY

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 2023 版本的文件

2023 版本默认为 STYLE_LEGACY,所以不符合规范的字段名是可以接受的

edition = "2023";

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

2025 版本默认为 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;
}

81fd217 (本文档更改包括以下内容:)

features.enum_type

此功能设置了如何处理不在定义集合内的枚举值的行为。有关开放和封闭枚举的更多信息,请参阅枚举行为

此功能不影响 proto3 文件,因此本节没有 proto3 文件的前后对比。

可用值

  • CLOSED:封闭枚举将超出范围的枚举值存储在未知字段集中。
  • OPEN:开放枚举直接将超出范围的值解析到其字段中。

适用于以下作用域:文件、枚举

添加于 2023

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024OPEN
2023OPEN
proto3OPEN
proto2CLOSED

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为:OPEN

语法/版本默认值
2024OPEN
2023OPEN
proto3OPEN
proto2CLOSED

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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_* 函数。

适用于以下作用域:文件、字段

«««< HEAD «««< HEAD 添加于:2023 ||||||| dcf50a2 的父版本 (本文档更改包括以下内容:) 在 2023 版本中的默认值: EXPLICIT

在 2023 版本中的默认行为: EXPLICIT

dcf50a2 (本文档更改包括以下内容:) ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 2023 版本中的默认行为: EXPLICIT ======= 添加于:2023 81fd217 (本文档更改包括以下内容:)

各语法/版本的默认行为

语法/版本默认值
2024EXPLICIT
2023EXPLICIT
proto3IMPLICIT*
proto2EXPLICIT

* proto3 是 IMPLICIT,除非字段带有 optional 标签,在这种情况下,其行为类似于 EXPLICIT。更多信息请参阅Proto3 API 中的存在性

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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 后,等效的代码可能如下所示

<<<<<<< HEAD
<<<<<<< HEAD
edition = "2024";
// Setting the file-level field_presence feature matches the proto3 implicit default
||||||| parent of dcf50a2 (This documentation change includes the following:)
edition = "2023";
=======
edition = "2023";
||||||| parent of 81fd217 (This documentation change includes the following:)
edition = "2023";
=======
edition = "2024";
>>>>>>> 81fd217 (This documentation change includes the following:)
// Setting the file-level field_presence feature matches the proto3 implicit default
>>>>>>> dcf50a2 (This documentation change includes the following:)
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

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024ALLOW
2023ALLOW
proto3ALLOW
proto2LEGACY_BEST_EFFORT

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为:ALLOW

语法/版本默认值
2024ALLOW
2023ALLOW
proto3ALLOW
proto2LEGACY_BEST_EFFORT

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 proto2 文件

syntax = "proto2";

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

运行 Prototiller 后,等效的代码可能如下所示

<<<<<<< HEAD
<<<<<<< HEAD
edition = "2024";
option features.json_format = LEGACY_BEST_EFFORT;
||||||| parent of dcf50a2 (This documentation change includes the following:)
edition = "2023";
features.json_format = LEGACY_BEST_EFFORT;
=======
edition = "2023";
||||||| parent of 81fd217 (This documentation change includes the following:)
edition = "2023";
=======
edition = "2024";
>>>>>>> 81fd217 (This documentation change includes the following:)
option features.json_format = LEGACY_BEST_EFFORT;
>>>>>>> dcf50a2 (This documentation change includes the following:)

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

features.message_encoding

此功能设置了序列化时字段的编码行为。

此功能不影响 proto3 文件,因此本节没有 proto3 文件的前后对比。

根据语言的不同,“类组”(group-like)字段在生成的代码和文本格式中可能会有一些意外的大小写,以提供与 proto2 的向后兼容性。消息字段在满足以下所有条件时是“类组”的

  • 指定了 DELIMITED 消息编码
  • 消息类型与字段在同一作用域内定义
  • 字段名恰好是类型名的小写形式

可用值

  • LENGTH_PREFIXED:字段使用消息结构中描述的 LEN wire type进行编码。
  • DELIMITED:消息类型字段被编码为

适用于以下作用域:文件、字段

添加于 2023

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024LENGTH_PREFIXED
2023LENGTH_PREFIXED
proto3LENGTH_PREFIXED
proto2LENGTH_PREFIXED

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为: LENGTH_PREFIXED。Proto3 不支持 DELIMITED

语法/版本默认值
2024LENGTH_PREFIXED
2023LENGTH_PREFIXED
proto3LENGTH_PREFIXED
proto2LENGTH_PREFIXED

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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 选项在版本中迁移到的目标。

可用值

  • PACKED:原始类型的 Repeated 字段被编码为单个 LEN 记录,其中包含每个元素的串联。
  • EXPANDEDRepeated 字段中的每个值都使用其字段号进行编码。

适用于以下作用域:文件、字段

添加于 2023

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024PACKED
2023PACKED
proto3PACKED
proto2EXPANDED

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为: PACKED

语法/版本默认值
2024PACKED
2023PACKED
proto3PACKED
proto2EXPANDED

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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 功能覆盖它。请参阅features.(pb.java).utf8_validation了解 Java 语言特定的功能。

此功能不影响 proto3 文件,因此本节没有 proto3 文件的前后对比。

可用值

  • VERIFY:运行时应验证 UTF-8。这是 proto3 的默认行为。
  • NONE:该字段在网络传输中的行为类似于未经验证的 bytes 字段。解析器可能以不可预测的方式处理此类字段,例如替换无效字符。这是 proto2 的默认行为。

适用于以下作用域:文件、字段

添加于 2023

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024VERIFY
2023VERIFY
proto3VERIFY
proto2NONE

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为: VERIFY

语法/版本默认值
2024VERIFY
2023VERIFY
proto3VERIFY
proto2NONE

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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.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

注意:不同 schema 元素上的功能设置具有不同的作用域

features.(pb.java).large_enum

语言:Java

这个特定于语言的功能使您能够采用新功能来处理 Java 中的大型枚举,而不会导致编译器错误。请注意,此功能复制了类似枚举的行为,但有一些显著差异。例如,不支持 switch 语句。

可用值

  • true:Java 枚举将使用新功能。
  • false:Java 枚举将继续使用 Java 枚举。

适用于以下作用域:枚举

添加于 2024

各语法/版本的默认行为

语法/版本默认值
2024false
2023false
proto3false
proto2false

注意:不同 schema 元素上的功能设置具有不同的作用域

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

语言:C++、Java

此功能决定了具有开放枚举类型的字段是否应表现得像封闭枚举。这使得版本能够在 Java 和 C++ 中重现 proto2 和 proto3 中的不合规行为

此功能不影响 proto3 文件,因此本节没有 proto3 文件的前后对比。

可用值

  • true:无论 enum_type 如何设置,都将枚举视为封闭的。
  • false:遵循 enum_type 中设置的任何内容。

适用于以下作用域:文件、字段

添加于 2023

各语法/版本的默认行为

语法/版本默认值
2024false
2023false
proto3false
proto2true

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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 生成的文件类中。将此选项设置为 Yes 相当于在 proto2/proto3/2023 版本中设置 java_multiple_files = true

默认的外部类名也更新为默认始终是驼峰式的 .proto 文件名,并以 Proto 为后缀(例如,foo/bar_baz.proto 变为 BarBazProto)。您仍然可以使用 java_outer_classname 文件选项覆盖此设置,并替换 2024 版本之前的默认值 BarBazBarBazOuterClass(取决于是否存在冲突)。

可用值

  • NO:不要将生成的类嵌套在文件类中。
  • YES:将生成的类嵌套在文件类中。
  • Legacy:设置 java_multiple_files 选项时使用的内部值。

适用于以下作用域:消息、枚举、服务

添加于 2024

各语法/版本的默认行为

语法/版本默认值
2024NO
2023LEGACY
proto3LEGACY
proto2LEGACY

注意:不同 schema 元素上的功能设置具有不同的作用域

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

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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

各语法/版本的默认行为

«««< HEAD

语法/版本默认值
2024DEFAULT
2023DEFAULT
proto3DEFAULT
proto2DEFAULT

注意:不同 schema 元素上的功能设置具有不同的作用域。 ||||||| 81fd217 的父版本 (本文档更改包括以下内容:) 在 proto3 中的行为: DEFAULT

语法/版本默认值
2024DEFAULT
2023DEFAULT
proto3DEFAULT
proto2DEFAULT

81fd217 (本文档更改包括以下内容:)

注意:不同 schema 元素上的功能设置具有不同的作用域

以下代码示例展示了一个 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;
}

保留 proto2 或 proto3 的行为

您可能希望迁移到版本格式,但暂时不想处理生成的代码行为的更新。本节展示了 Prototiller 工具对您的 .proto 文件所做的更改,以使基于版本的 proto 表现得像 proto2 或 proto3 文件一样。

在文件级别进行这些更改后,您将获得 proto2 或 proto3 的默认行为。您可以在更低的级别(消息级别、字段级别)进行覆盖,以考虑其他行为差异(例如required、proto3 optional),或者如果您希望您的定义只是*大部分*像 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 版本行为的设置。

edition = "2024";

import option "third_party/protobuf/cpp_features.proto";
import option "third_party/java/protobuf/java_features.proto";

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.java).nest_in_file_class = LEGACY;

注意事项和例外

本节展示了如果您选择不使用 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 文件,移除 packed 字段选项,并在您不希望使用在Proto2 行为中设置的 EXPANDED 行为时,在字段级别添加 [features.repeated_field_encoding=PACKED]。对于转换为版本格式的 proto3 文件,当您不希望使用默认的 proto3 行为时,在字段级别添加 [features.repeated_field_encoding=EXPANDED]

2024 版本及更高版本