入门指南
本指南介绍所有受支持语言中跨语言序列化的安装与基础设置。
安装
Java
Maven:
<dependency>
<groupId>org.apache.fory</groupId>
<artifactId>fory-core</artifactId>
<version>1.1.0</version>
</dependency>
Gradle:
implementation 'org.apache.fory:fory-core:1.1.0'
Python
pip install pyfory
Go
go get github.com/apache/fory/go/fory
Rust
[dependencies]
fory = "1.1.0"
JavaScript/TypeScript
npm install @apache-fory/core
对于可选的 Node.js 字符串快速路径:
npm install @apache-fory/core @apache-fory/hps
C#
dotnet add package Apache.Fory --version 1.1.0
Dart
dart pub add fory:^1.1.0
dart pub add dev:build_runner
Swift
将 Fory 添加到 Package.swift:
dependencies: [
.package(url: "https://github.com/apache/fory.git", exact: "1.1.0")
]
Scala
libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.1.0"
Kotlin
implementation("org.apache.fory:fory-kotlin:1.1.0")
C++
使用 Bazel 或 CMake 从源码构建。详见 C++ 指南。
创建 Xlang 运行时
对于暴露模式开关的运行时,Xlang 模式是默认选项。Swift、C#、JavaScript/TypeScript 和 Dart 只暴露 xlang 编码格式。下面的示例将兼容的 Schema 演进保留在默认路径上,只展示会改变其他设置的选项。
Java
import org.apache.fory.*;
import org.apache.fory.config.*;
Fory fory = Fory.builder()
.withXlang(true)
.withRefTracking(true) // Optional: for circular references
.build();
Python
import pyfory
fory = pyfory.Fory(xlang=True)
# Enable reference tracking when needed
fory = pyfory.Fory(xlang=True, ref=True)
Go
import forygo "github.com/apache/fory/go/fory"
fory := forygo.NewFory(forygo.WithXlang(true))
// Or with reference tracking
fory := forygo.NewFory(forygo.WithXlang(true), forygo.WithTrackRef(true))
Rust
use fory::Fory;
let fory = Fory::builder().xlang(true).build();
JavaScript/TypeScript
import Fory, { Type } from "@apache-fory/core";
const fory = new Fory();
C#
using Apache.Fory;
Fory fory = Fory.Builder().Build();
Dart
import 'package:fory/fory.dart';
final fory = Fory();
Swift
import Fory
let fory = Fory()
Scala
import org.apache.fory.scala.ForyScala
val fory = ForyScala.builder()
.withXlang(true)
.build()
Kotlin
import org.apache.fory.kotlin.ForyKotlin
val fory = ForyKotlin.builder()
.withXlang(true)
.build()
C++
#include "fory/serialization/fory.h"
using namespace fory::serialization;
auto fory = Fory::builder().xlang(true).build();
类型注册
自定义类型必须在所有语言中使用一致的名称或 ID 注册。
按名称注册(推荐)
使用字符串名称更灵活,也更不容易发生冲突:
Java:
fory.register(Person.class, "example.Person");
Python:
fory.register_type(Person, typename="example.Person")
Go:
fory.RegisterStructByName(Person{}, "example.Person")
Rust:
use fory::{Fory, ForyStruct};
#[derive(ForyStruct)]
struct Person {
name: String,
age: i32,
}
let mut fory = Fory::builder().xlang(true).build();
fory
.register_by_name::<Person>("example", "Person")
.expect("register Person");
JavaScript/TypeScript:
const personType = Type.struct(
{ typeName: "example.Person" },
{
name: Type.string(),
age: Type.int32(),
},
);
const { serialize, deserialize } = fory.register(personType);
C++:
fory.register_struct<Person>("example", "Person");
// For enums, use register_enum:
// fory.register_enum<Color>("example", "Color");
C#:
fory.Register<Person>("example", "Person");
Dart:
PersonForyModule.register(
fory,
Person,
namespace: 'example',
typeName: 'Person',
);
Swift:
try fory.register(Person.self, namespace: "example", name: "Person")
Scala:
fory.register(classOf[Person], "example.Person")
Kotlin:
fory.register(Person::class.java, "example.Person")
按 ID 注册
使用数字 ID 速度更快,并且生成的二进制输出更小:
Java:
fory.register(Person.class, 100);
Python:
fory.register_type(Person, type_id=100)
Go:
fory.RegisterStruct(Person{}, 100)
Rust:
fory.register::<Person>(100)?;
JavaScript/TypeScript:
const personType = Type.struct(
{ typeId: 100 },
{
name: Type.string(),
age: Type.int32(),
},
);
C++:
fory.register_struct<Person>(100);
// For enums, use register_enum:
// fory.register_enum<Color>(101);
C#:
fory.Register<Person>(100);
Dart:
PersonForyModule.register(fory, Person, id: 100);
Swift:
fory.register(Person.self, id: 100)
Scala:
fory.register(classOf[Person], 100)
Kotlin:
fory.register(Person::class.java, 100)
Hello World 示例
下面给出一个完整示例,展示如何在 Java 中序列化、在 Python 中反序列化:
Java(序列化端)
import org.apache.fory.*;
import org.apache.fory.config.*;
import java.nio.file.*;
public class Person {
public String name;
public int age;
}
public class HelloWorld {
public static void main(String[] args) throws Exception {
Fory fory = Fory.builder().withXlang(true).build();
fory.register(Person.class, "example.Person");
Person person = new Person();
person.name = "Alice";
person.age = 30;
byte[] bytes = fory.serialize(person);
Files.write(Path.of("person.bin"), bytes);
System.out.println("Serialized to person.bin");
}
}
Python(反序列化端)
import pyfory
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: pyfory.Int32
fory = pyfory.Fory(xlang=True)
fory.register_type(Person, typename="example.Person")
with open("person.bin", "rb") as f:
data = f.read()
person = fory.deserialize(data)
print(f"Name: {person.name}, Age: {person.age}")
# Output: Name: Alice, Age: 30
最佳实践
- 使用一致的类型名:确保所有语言使用相同的类型名或 ID。
- 启用引用跟踪:如果你的数据包含循环引用或共享引用。
- 复用 Fory 实例:创建 Fory 实例成本较高,应尽量复用。
- 使用类型注解:在 Python 中使用
pyfory.Int32等标记来获得精确的类型映射。 - 测试跨语言链路:验证序列化在所有目标语言之间都能正确工作。