Version 30.x 新闻公告

Protocol Buffers 版本 30.x 宣布的变更。

以下公告特定于 Version 30.x。有关按时间顺序呈现的信息,请参阅 新闻

以下章节涵盖了计划在 2025 年第一季度发布的 v30 版本中的重大更改。还包括一些非破坏性的更改,但可能需要您采取措施。这些描述了我们预计的实施方式的更改,但由于软件的灵活性,其中一些更改可能不会落地,或者可能与本主题中的描述有所不同。

C++ 中的变更

C++ 将其主版本从 5.29.x 提升到 6.30.x。

Descriptor API

v30 将更新描述符(例如 full_name)中的返回类型为 absl::string_view。这可以节省描述符中的内存。

v28 引入了 PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE 宏,您可以暂时使用它来在破坏性发布之前启用更新的返回类型。v30 版本将翻转默认值并删除该宏。

ctype 从 FieldDescriptor Options 中移除

v30 将停止从 FieldDescriptor 选项中公开 ctype。您可以使用 v28 版本 中添加的 FieldDescriptor::cpp_string_type() API 来代替它。

用 Fetched Deps 替换 CMake 子模块

v30 将删除子模块并切换到 upb 的旧 CMake 模式来获取依赖项。

如果您使用已安装的软件包,则不会受到影响。它可能会破坏一些 CMake 工作流程。

修改 Debug API 以编辑敏感字段

我们计划在 v30 中修改 Protobuf 调试 API(包括 Protobuf AbslStringify、proto2::ShortFormatproto2::Utf8FormatMessage::DebugStringMessage::ShortDebugStringMessage::Utf8DebugString),以编辑由 debug_redact 注释的敏感字段;这些 API 的输出将包含每个进程的随机前缀,因此 Protobuf TextFormat 解析器将不再可解析它们。

请在 2024 年 11 月 21 日发布的新闻文章中阅读有关此内容的更多信息。

移除与反射相关的函数

我们正在移除以下与反射相关的函数:MutableRepeatedFieldRef<T>::Reserve()

RepeatedPtrField 中即将到来的性能改进与此 API 不兼容。预计该改进将加速重复访问 RepeatedPtrField 的元素,尤其是顺序访问。

移除已弃用的 API

v30 将删除以下公共运行时 API,这些 API 已被标记为已弃用 (例如 ABSL_DEPRECATED) 至少一个次要或主要版本,并且已过时或被替换。

Arena::CreateMessage

API: Arena::CreateMessage

替代方案: Arena::Create

Arena::GetArena

API: Arena::GetArena

替代方案: value->GetArena()

RepeatedPtrField::ClearedCount

API: RepeatedPtrField::ClearedCount

替代方案: 迁移到 Arena (迁移指南)。

JsonOptions

API: JsonOptions

替代方案: JsonPrintOptions

放弃 C++14 支持

此版本将放弃 C++ 14 作为最低支持版本,并将其提升到 17,根据 Foundational C++ Support matrix

根据 我们的政策,我们不认为这是一个破坏性更改。

在 Arena 上清除 Oneof 消息后引入 ASAN Poisoning

此更改添加了一个硬化检查,会影响使用 Arena 的 C++ protobuf。在 protobuf arena 上分配的 Oneof 消息现在将在调试模式下清除,并在 ASAN 模式下中毒。调用 clear 后,将来尝试使用该内存区域将导致 ASAN 崩溃,并显示 use-after-free 错误。

此实现需要 C++17。

放弃我们的 C++ CocoaPods 发布

在 v30 中,我们将放弃我们的 C++ CocoaPods 发布,该发布自 v4.x.x 以来一直处于损坏状态。C++ 用户应直接使用我们的 GitHub 发布

JRuby 中的变更

v30 将翻转 JRuby 的默认实现为 FFI,这对于某些 JRuby 用户来说可能是破坏性的。

请注意,此更改不会创建 Ruby 主版本号提升,因为 JRuby 未获得官方支持

Python 中的变更

Python 将其主版本从 5.29.x 提升到 6.30.x。

放弃 Python 3.8 支持

根据我们的官方 Python 支持政策,我们将放弃对 Python 3.8 及更低版本的支持。这意味着最低支持的 Python 版本是 3.9。

移除 bazel/system_python.bzl 别名

v30 将移除旧的 bazel/system_python.bzl 别名。

删除对 system_python.bzl 的直接引用,而改为使用 protobuf_deps.bzl。如果您需要直接引用,请使用 v5.27.0 中 移动到的 python/dist/system_python.bzl

字段 Setter 验证变更

Python 和 upb 的字段 setter 将在 v30 中修复,以验证 2023 版本下的封闭枚举。使用无效值更新的封闭枚举字段将生成错误。

移除已弃用的 py_proto_library 宏

已弃用的内部 py_proto_library Bazel 宏在 protobuf.bzl 中将在 v30.x 中移除。

这应该由官方的 py_proto_library 替换,该宏将在 v29.x 时移动到 protobuf 中的 bazel/py_proto_library。此实现在 v29.x 之前的 rules_python 中可用。

移除已弃用的 API

v30 将移除以下公共运行时 API,这些 API 已被标记为已弃用至少一个次要或主要版本,并且已过时或被替换。

反射方法

API: reflection.ParseMessage, reflection.MakeClass

替代方案: message_factory.GetMessageClass()

RPC 服务接口

API: service.RpcException, service.Service, service.RpcController, 和 service.RpcChannel

替代方案: 从 2.3.0 版本开始,RPC 实现不应尝试基于这些构建,而应提供代码生成器插件,这些插件生成特定于特定 RPC 实现的代码。

MessageFactory 和 SymbolDatabase 方法

API: MessageFactory.GetPrototype, MessageFactory.CreatePrototype, MessageFactory.GetMessages, SymbolDatabase.GetPrototype, SymbolDatabase.CreatePrototype, 和 SymbolDatabase.GetMessages

替代方案: message_factory.GetMessageClass()message_factory.GetMessageClassesForFiles()

GetDebugString

API: GetDebugString

替代方案

没有替代方案。它仅在不再发布的 Python C++ 中。纯 Python 或 UPB 中不支持它。

Python setdefault 对 Map 字段的行为变更

从 v30 开始,setdefault 对于 ScalarMap 将类似于 dict,只是键和值都必须设置。setdefault 将被 MessageMaps 拒绝。

Python 嵌套消息类 __qualname__ 包含外部消息名称

Python 嵌套消息类 __qualname__ 现在包含外部消息名称。在 v30 之前,__qualname__ 与嵌套消息的 __name__ 具有相同的结果,因为不包括外部消息名称。

例如

message Foo {
  message Bar {
    bool bool_field = 1;
  }
}
nested = test_pb2.Foo.Bar()
self.assertEqual('Bar', nested.__class__.__name__)
self.assertEqual('Foo.Bar', nested.__class__.__qualname__) # It was 'Bar' before

Objective-C 中的变更

这将是 Objective-C 的第一个破坏性版本.

Objective-C 将其主版本从 3.x.x 提升到 4.30.x。

彻底改革未知字段处理 API,弃用大多数现有 API

v30 将弃用 GPBUnknownFieldSet,并将其替换为 GPBUnknownFields。新类型将保留来自原始输入或 API 调用的未知字段的顺序,以确保在将消息写回时维护顺序的任何语义含义。

作为此操作的一部分,GPBUnknownField 类型的 API 也已更改,几乎所有现有 API 都已弃用,并添加了新的 API。

已弃用的属性 API

  • varintList
  • fixed32List
  • fixed64List
  • lengthDelimitedList
  • groupList

已弃用的修改 API

  • addVarint
  • addFixed32
  • addFixed64
  • addLengthDelimited
  • addGroup

已弃用的初始化程序 initWithNumber:

新的属性 API

  • type
  • varint
  • fixed32
  • fixed64
  • lengthDelimited
  • group

此类型将对其值中的单个字段编号建模,而不是分组给定字段编号的所有值。用于创建新字段的 API 是 GPBUnknownFields 类上的 add* API。

v30 还将弃用 -[GPBMessage unknownFields]。在其位置,将有新的 API 来提取和更新消息的未知字段。

移除已弃用的 API

v30 将移除以下公共运行时 API,这些 API 已被标记为已弃用至少一个次要或主要版本,并且已过时或被替换。

GPBFileDescriptor

API: -[GPBFileDescriptor syntax]

替代方案: 已过时。

GPBMessage mergeFrom:extensionRegistry

API: -[GPBMessage mergeFrom:extensionRegistry:]

替代方案: -[GPBMessage mergeFrom:extensionRegistry:error:]

GPBDuration timeIntervalSince1970

API: -[GPBDuration timeIntervalSince1970]

替代方案: -[GPBDuration timeInterval]

GPBTextFormatForUnknownFieldSet

API: GPBTextFormatForUnknownFieldSet()

替代方案: 已过时 - 使用 GPBTextFormatForMessage(),其中包括任何未知字段。

GPBUnknownFieldSet

API: GPBUnknownFieldSet

替代方案: GPBUnknownFields

GPBMessage unknownFields

API: GPBMessage unknownFields 属性

替代方案: -[GPBUnknownFields initFromMessage:], -[GPBMessage mergeUnknownFields:extensionRegistry:error:], 和 -[GPBMessage clearUnknownFields]

移除旧 Gencode 的已弃用运行时 API

此版本将移除支持 3.22.x 版本之前的 Objective-C gencode 的已弃用运行时方法。当旧的生成的代码启动时,该库还将在运行时发出日志消息。

API: +[GPBFileDescriptor allocDescriptorForClass:file:fields:fieldCount:storageSize:flags:]

替代方案: 使用当前版本的库重新生成。

API: +[GPBFileDescriptor allocDescriptorForClass:rootClass:file:fields:fieldCount:storageSize:flags:]

替代方案: 使用当前版本的库重新生成。

API: +[GPBEnumDescriptor allocDescriptorForName:valueNames:values:count:enumVerifier:]

替代方案: 使用当前版本的库重新生成。

API: +[GPBEnumDescriptor allocDescriptorForName:valueNames:values:count:enumVerifier:extraTextFormatInfo:]

替代方案: 使用当前版本的库重新生成。

API: -[GPBExtensionDescriptor initWithExtensionDescription:]

替代方案: 使用当前版本的库重新生成。

其他变更

Poison MSVC + Bazel

我们将放弃在 v34 中一起使用 Bazel 和 MSVC 的支持。从 v30 开始,我们将 Poison 此组合并显示错误,除非您指定选择退出标志 --define=protobuf_allow_msvc=true 以使其静音。

MSVC 的路径长度限制与 Bazel 的沙箱机制结合使用,变得越来越难以支持。与其随机破坏将 protobuf 安装到长路径中的用户,我们将完全禁止从 Bazel 使用 MSVC。我们将继续支持带有 CMake 的 MSVC,并开始支持带有 Bazel 的 clang-cl。对于任何反馈或讨论,请参阅 https://github.com/protocolbuffers/protobuf/issues/20085

其他变更 (非破坏性)

除了这些破坏性更改之外,还有一些其他值得注意的更改。虽然以下内容不被认为是破坏性更改,但仍可能影响用户。

Poison Pill 警告

v30 将更新 poison pills,以便为新的滚动升级策略下可以工作但在下一个主要版本升级中会中断的旧 gencode + 新运行时组合发出警告。例如,Java 4.x.x gencode 应该可以针对 5.x.x 运行时工作,但会警告即将到来的针对 6.x.x 运行时的中断。

C# 和 Ruby 中 UTF-8 强制执行的变更

v30 将包含一个修复程序,以使 UTF-8 强制执行在各种语言中保持一致。字符串字段中包含错误非 UTF-8 数据的用户可能会更早地看到表面化的 UTF-8 强制执行错误。

Ruby 和 PHP 在 JSON 解析中出错

v30 修复了 JSON 解析中数字字段中字符串的不一致性,根据 JSON 规范

此修复程序不会伴随主版本号提升,但 Ruby 和 PHP 现在将为数字字段中的非数字字符串(例如“”、“12abc”、“abc”)引发错误。v29.x 将包含针对这些错误情况的警告。