Apache Fory 1.7.5 正式发布! 本次更新包含 4 位贡献者提交的 15 个 PR,新增多项 JSON 输出配置,完善 Scala 和 Kotlin JSON 类型与默认值处理,并扩展 Python 集合及时间类型数据的序列化支持。
Apache Fory 是一个高性能的多语言序列化框架,面向应用对象、跨语言数据交换和数据存储,提供二进制对象序列化、Schema IDL、Row Format 等能力,支持 Java、Python、C++、Go、Rust、JavaScript/TypeScript、C#、Swift、Dart、Scala 和 Kotlin。
对于使用标准 JSON 的应用,Fory JSON 提供 Java、Kotlin 和 Scala 对象的 JSON 读写能力。1.7.5 进一步丰富输出选项,让应用能够根据接口约定选择格式化输出、字符转义、字节数组表示和默认值省略策略。
项目地址:
https://github.com/apache/fory
本次发布的主要亮点:
- • 更灵活的 JSON 输出:支持按次调用选择格式化输出、非 ASCII 字符转义、包含 Base16 的字节数组格式,以及显式启用的默认值省略。
- • 更完善的 Scala 和 Kotlin JSON 支持:扩展类型覆盖,完善字段缺失时的默认值处理,并修复 Java JSON 在 GraalVM Native Image 中的兼容问题。
- • 更丰富的 Python 集合支持:支持集合接口和已注册的集合子类,修复具名元组重建,并扩展时间类型数组的带外缓冲区支持。
一、JSON 输出:按应用需要选择表示方式
按次调用选择格式化输出
应用在接口传输时通常使用紧凑 JSON,在调试或人工查看时则需要带缩进的格式化结果。1.7.5 可以复用同一个 ForyJson 实例,在每次调用时选择输出方式:
import java.util.Collections;
import org.apache.fory.json.ForyJson;
ForyJson json = ForyJson.builder().build();
String pretty = json.toPrettyJson(Collections.singletonMap("name", "Fory"));
byte[] prettyBytes = json.toPrettyJsonBytes(Collections.singletonMap("name", "Fory"));
String compact = json.toJson(Collections.singletonMap("name", "Fory"));
toPrettyJson 返回格式化字符串,toPrettyJsonBytes 返回格式化后的 UTF-8 字节数组;原有 toJson 调用仍可用于紧凑输出。
支持非 ASCII 字符转义
当接口要求将中文等非 ASCII 字符表示为 JSON Unicode 转义时,可以启用 escapeNonAscii(true):
import org.apache.fory.json.ForyJson;
ForyJson json = ForyJson.builder()
.escapeNonAscii(true)
.build();
String text = json.toJson("你好");
输出结果:
"\u4f60\u597d"
该选项同时作用于字符串值和属性名称,改变的是 JSON 中的字符表示方式,解码后的文本内容保持一致。
字节数组支持 Base64、Base16 和数字数组
不同接口对二进制数据的表示方式可能有不同约定。1.7.5 新增全局 byteArrayFormat 配置,可为普通字节数组选择 Base64 字符串、Base16 十六进制字符串或有符号数字数组,并适用于嵌套值。
例如,使用 Base16 输出字节数组:
import org.apache.fory.json.ForyJson;
import org.apache.fory.json.annotation.JsonByteArray;
ForyJson hexJson = ForyJson.builder()
.byteArrayFormat(JsonByteArray.Format.BASE16)
.build();
String text = hexJson.toJson(new byte[] {1, -2, 3});
byte[] bytes = hexJson.fromJson(text, byte[].class);
对应的 JSON 输出为:
"01fe03"
如果某个属性需要使用不同格式,可以通过属性级 JsonByteArray 注解覆盖全局默认设置。
显式省略默认值
对于字段缺失时能够恢复默认值的数据模型,应用可以通过省略默认属性减少重复信息。1.7.5 支持通过属性上的 JsonProperty 或类上的 JsonInclude,显式启用 NON_DEFAULT 策略。
省略默认值的前提是:默认值稳定、可安全求值,并且字段缺失时能够恢复一致的值。 应用应根据具体数据模型启用该策略;全局
NON_DEFAULT 配置会被拒绝。
同时,Scala 的 NON_EMPTY 策略也扩展了空值识别范围,支持 None,以及受支持的空严格求值集合和 Map。
JSON 输出配置:
https://fory.apache.org/zh-CN/docs/json/object-mapping/
默认值省略的适用模型与配置示例:
https://fory.apache.org/zh-CN/docs/json/annotations#jsoninclude-and-default-omission
二、Scala 与 Kotlin:完善类型支持和缺失字段处理
扩展 Scala JSON 类型覆盖
1.7.5 完善了 Scala 泛型 case class、Unit 和枚举类型令牌的支持。对于由单例分支组成的 sealed 类型层次,应用还可以显式选择字符串编解码器。
这些改进进一步完善了 Scala 数据模型与 JSON 之间的映射。具体支持范围与配置方式,可参阅 Scala JSON 指南:
https://fory.apache.org/zh-CN/docs/json/scala/
明确字段缺失时的默认值行为
反序列化 JSON 时,缺失字段应按照数据模型的声明恢复。1.7.5 完善了 Scala 和 Kotlin 的相关处理:
- • Scala:使用声明的构造函数默认值或类型默认值。
- • Kotlin:优先使用声明的默认值;没有声明默认值时,非空数值参数使用零,非空 Boolean 参数使用
false,可空参数使用 null。 - • 其他非空 Kotlin 参数仍为必需参数,例如未声明默认值的非空字符串参数。
上述规则针对字段缺失的情况。显式传入 null 时的具体行为,应遵循相应语言的类型与可空性约定。
Kotlin JSON 指南:
https://fory.apache.org/zh-CN/docs/json/kotlin/
本次发布还修复了 Java JSON 访问器在 GraalVM Native Image 中的处理,完善原生镜像场景下的兼容性。
三、Python:扩展集合与时间类型缓冲区支持
跨语言模式支持更多集合实现
Python 应用中,数据不一定直接存放在内置 dict、list 或 set 中,也可能使用实现了集合接口的自定义类型。
1.7.5 的跨语言(Xlang)模式支持 Mapping、Sequence 和 Set 的实现及其可变变体。反序列化时,这些集合中的值会恢复为内置 dict、list 和
set 对象。
原生模式保留已注册的集合子类
对于仅在 Python 中使用、需要保留自定义集合类型的场景,Python 原生模式支持已注册的 list、dict 和 set 子类,并保留其实例状态。
跨语言模式侧重集合值的互通,Python 原生模式则支持保留已注册集合子类的类型与状态。 应用可根据数据交换范围选择相应模式。
Python 集合接口说明:
https://fory.apache.org/zh-CN/docs/object-serialization/python/basic-serialization#collection-interfaces
Python 原生模式:
https://fory.apache.org/zh-CN/docs/object-serialization/python/native/
完善具名元组和时间类型数组处理
本次发布修复了 Python 原生模式下的具名元组重建,并为以下数据增加带外缓冲区支持:
带外序列化允许将相关缓冲区与主序列化数据分开交付,便于应用结合自身的传输方式处理数组数据。
带外序列化示例:
https://fory.apache.org/zh-CN/docs/object-serialization/python/out-of-band/
四、完整更新记录
本次 1.7.5 共包含 15 个 PR。
功能、性能与测试改进
- • 优化 JSON 字符串解码中转义片段之间的连续文本复制,@pavel-ptashyts。
https://github.com/apache/fory/pull/4058 - • 共享 JSON reader 与 writer 的字节缓冲区,@chaokunyang。
https://github.com/apache/fory/pull/4061 - • 支持 Python 集合子类,@chaokunyang。
https://github.com/apache/fory/pull/4063 - • 完善 JSON 类型支持,@chaokunyang。
https://github.com/apache/fory/pull/4064 - • 补充 Scala JSON 文档所列类型及错误路径的测试覆盖,@pjfanning。
https://github.com/apache/fory/pull/4070 - • 支持按次调用输出格式化 JSON 字符串和字节数组,@chaokunyang。
https://github.com/apache/fory/pull/4073 - • 支持显式默认值省略,并完善 Scala 空值过滤,@chaokunyang。
https://github.com/apache/fory/pull/4074 - • 支持全局字节数组格式配置与 Base16,@chaokunyang。
https://github.com/apache/fory/pull/4075 - • 支持非 ASCII 字符转义,@chaokunyang。
https://github.com/apache/fory/pull/4077
问题修复
- • 修复 Java JSON 访问器的 GraalVM 构建期处理,@zhfeng。
https://github.com/apache/fory/pull/4060 - • 修复 Python 具名元组及时间类型数组缓冲区处理,@chaokunyang。
https://github.com/apache/fory/pull/4062 - • 缓存 JSON 方法 Lambda 的可见性检查结果,@chaokunyang。
https://github.com/apache/fory/pull/4071 - • 修复 Scala 编解码器及 Scala/Kotlin 缺失字段的默认值处理,@chaokunyang。
https://github.com/apache/fory/pull/4072 - • 远端 Schema 缓存配额耗尽后,继续解码而不再写入缓存,@chaokunyang。
https://github.com/apache/fory/pull/4076
文档更新
- • 将文档中的发布版本更新至 1.7.4,@chaokunyang。这是本次发布区间内合入的上一版本文档更新。
https://github.com/apache/fory/pull/4065
感谢 @chaokunyang、@pavel-ptashyts、@pjfanning 和 @zhfeng 的贡献,也欢迎首次参与贡献的 @pavel-ptashyts!
完整变更日志(v1.7.4 → v1.7.5):
https://github.com/apache/fory/compare/v1.7.4...v1.7.5
五、获取 Apache Fory 1.7.5
Java JSON
<dependency>
<groupId>org.apache.forygroupId>
<artifactId>fory-jsonartifactId>
<version>1.7.5version>
dependency>
Kotlin JSON
implementation("org.apache.fory:fory-json-kotlin:1.7.5")
同一应用中的各 Fory 模块应使用相同版本。
Python
pip install pyfory==1.7.5
更多语言的安装方式与快速开始:
https://fory.apache.org/zh-CN/docs/start/
源码下载:
https://fory.apache.org/zh-CN/download/
中文发布博客:
https://fory.apache.org/zh-CN/blog/fory_1_7_5_release/
官方 Release Notes:
https://github.com/apache/fory/releases/tag/v1.7.5
欢迎试用 Apache Fory 1.7.5,并在 GitHub 提交问题、分享使用体验或参与贡献。
https://github.com/apache/fory