跨语言序列化
Fory JavaScript 与 Java、Python、Go、Rust、Swift 和 C++ 的 Fory 运行时使用相同的二进制格式进行序列化。你可以在 JavaScript 中写入消息,再在 Java 中读取它,反过来也一样,无需额外的转换层。
需要注意:
- Fory JavaScript 运行时只读写跨语言载荷,不支持任何语言原生格式。
- 当前暂不支持 out-of-band mode。
成功完成往返的要求
要让一条消息能在 JavaScript 与另一种运行时之间稳定往返,双方必须满足:
- 两端具有相同的类型标识,即相同的数值 ID,或相同的
namespace + typeName - 字段类型兼容,例如 JavaScript 中的
Type.int32()字段应对应 Javaint、Goint32、C#int - 可空性一致,如果一侧把字段标记为可空,另一侧也应如此
- 如果使用 Schema 演进,双方的
compatible模式必须一致 - 如果数据包含共享引用或循环引用,双方的引用跟踪配置也必须一致
分步说明:从 JavaScript 到其他运行时
- 在 JavaScript 中使用与其他运行时相同的类型名称或数值 ID 定义 schema
- 在两端都注册该 schema
- 对齐字段类型、可空性和
compatible设置 - 在发布前对真实载荷做端到端测试
JavaScript 侧:
import Fory, { Type } from "@apache-fory/core";
const messageType = Type.struct(
{ typeName: "example.message" },
{
id: Type.int64(),
content: Type.string(),
},
);
const fory = new Fory();
const { serialize } = fory.register(messageType);
const bytes = serialize({
id: 1n,
content: "hello from JavaScript",
});
在另一侧,请使用对应运行时的 API 注册同一个 example.message 类型,即相同的名称或相同的数值 ID:
字段命名
Fory 按字段名匹配字段。当模型在多种语言中定义时,应保持字段名一致,或者至少采用能够在不同语言间无歧义映射的命名方案,例如统一使用 snake_case。
当使用 compatible: true 进行 Schema 演进时,字段顺序的差异是允许的,但字段名本身仍必须一致。
数值类型
JavaScript 的 number 是 64 位浮点数,无法与其他语言中的所有整数类型一一对应。因此应使用显式 schema 类型:
Type.int32():用于 32 位整数,对应 Javaint、Goint32、C#intType.int64():配合bigint值使用,用于 64 位整数,对应 Javalong、Goint64Type.float32()或Type.float64():用于浮点数
日期与时间
Type.timestamp():表示一个时间点;往返后仍是 JavaScriptDateType.date():表示不带时间的日期;反序列化结果为DateType.duration():在 JavaScript 中暴露为毫秒数
多态字段
Type.any() 允许字段在运行时承载不同类型的值,但它在跨语言场景中更难保持一致。只要可能,就应优先使用显式字段 schema。
const wrapperType = Type.struct(
{ typeId: 3001 },
{
payload: Type.any(),
},
);
枚举
枚举成员的顺序必须在不同语言间保持一致。Fory 按 ordinal position 而不是按枚举值对枚举进行编码。
const Color = { Red: 1, Green: 2, Blue: 3 };
const fory = new Fory();
fory.register(Type.enum({ typeId: 210 }, Color));
在每个对端运行时中都应使用相同的类型 ID 或类型名。