Skip to main content
Version: 1.1.0

Getting Started

This guide covers installation and basic setup for cross-language serialization in all supported languages.

Installation

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

For the optional Node.js string fast path:

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

Add Fory to 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++

Use Bazel or CMake to build from source. See C++ Guide for details.

Create an Xlang Runtime

Xlang mode is the default for runtimes that expose a mode switch. Swift, C#, JavaScript/TypeScript, and Dart only expose the xlang wire format. The examples below keep compatible schema evolution on the default path and show only options that change another setting.

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();

Type Registration

Custom types must be registered with consistent names or IDs across all languages.

Using string names is more flexible and less prone to conflicts:

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")

Register by ID

Using numeric IDs is faster and produces smaller binary output:

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 Example

A complete example showing serialization in Java and deserialization in Python:

Java (Serializer)

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 (Deserializer)

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

Best Practices

  1. Use consistent type names: Ensure all languages use the same type name or ID
  2. Enable reference tracking: If your data has circular or shared references
  3. Reuse Fory instances: Creating Fory is expensive; reuse instances
  4. Use type annotations: In Python, use markers such as pyfory.Int32 for precise type mapping
  5. Test cross-language: Verify serialization works across all target languages

Next Steps