MCPcopy Index your code
hub / github.com/apache/fory

github.com/apache/fory @v1.3.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.3.0 ↗ · + Follow
30,416 symbols 131,713 edges 1,525 files 4,189 documented · 14%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Apache Fory logo

Build Status Slack Channel X Maven Version Crates.io PyPI npm NuGet pub.dev

Apache Fory™ is a blazingly fast multi-language serialization framework for idiomatic domain objects, schema IDL, and cross-language data exchange.

https://fory.apache.org

Why Fory

Fory is built for fast, compact serialization across languages and implementations. It works with idiomatic objects in each language, supports shared schemas when you need a contract, and preserves object features such as shared and circular references.

  • Efficient Cross-Language Encoding: Exchange payloads across supported languages with compact binary encoding, metadata packing, schema evolution, shared/circular references, and polymorphic runtime types.
  • Domain Objects First: Serialize Java classes, Python dataclasses, Go structs, Rust/C++ structs, and generated or annotated model types directly. Preserve shared and circular references when object identity matters.
  • Reference-Aware Schema IDL: Support shared and circular references directly in the schema, alongside numbers, strings, lists, maps, arrays, enums, structs, and unions. Define schemas once, then generate native domain objects for each language without forcing wrapper types into user code.
  • Row-Format Random Access: Read fields, arrays, and nested values without rebuilding full objects, with zero-copy access and partial reads.
  • Optimized Implementations: Java JIT serializers and generated/static serializers in other language implementations keep hot paths fast and payloads compact.
  • Language And Platform Support: Java, Python, C++, Go, Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin, including GraalVM native image, Android, Dart VM/Flutter/web, and Node.js/browser JavaScript.

Performance

Benchmarks show Fory delivering higher throughput and smaller serialized payloads than common serialization frameworks on representative workloads. Java has the broadest comparison set; the other charts show language-specific results across supported languages.

Java Benchmarks

In Java serialization benchmarks, Fory reaches up to 170x the throughput of JDK serialization on selected workloads.

Java serialization throughput

Java deserialization throughput

Java xlang throughput

Python Benchmarks

Python serialization throughput

Rust Benchmarks

Rust serialization throughput

Benchmarks for C++, Go, JavaScript/TypeScript, C#, Swift, and Dart

C++ Benchmarks

C++ serialization throughput

Go Benchmarks

Go serialization throughput

JavaScript/TypeScript Benchmarks

JavaScript serialization throughput

C# Benchmarks

C# serialization throughput

Swift Benchmarks

Swift serialization throughput

Dart Benchmarks

Dart serialization throughput

Installation

Pick your language and run the package-manager command, or paste the dependency block into your build file.

Java

Maven:

<dependency>
  <groupId>org.apache.fory</groupId>
  <artifactId>fory-core</artifactId>
  <version>1.2.0</version>
</dependency>

Gradle:

implementation "org.apache.fory:fory-core:1.2.0"

On JDK25+, open java.lang.invoke to Fory. Use ALL-UNNAMED when Fory is on the classpath:

--add-opens=java.base/java.lang.invoke=ALL-UNNAMED

Use the Fory core module name when Fory is on the module path:

--add-opens=java.base/java.lang.invoke=org.apache.fory.core

Scala

sbt:

libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.2.0"

Kotlin

Gradle:

implementation("org.apache.fory:fory-kotlin:1.2.0")

Maven:

<dependency>
  <groupId>org.apache.fory</groupId>
  <artifactId>fory-kotlin</artifactId>
  <version>1.2.0</version>
</dependency>

Python

pip install pyfory

For row-format support:

pip install "pyfory[format]"

Rust

Cargo.toml:

[dependencies]
fory = "1.2.0"

C++

CMake:

include(FetchContent)
FetchContent_Declare(
  fory
  GIT_REPOSITORY https://github.com/apache/fory.git
  GIT_TAG v1.2.0
  SOURCE_SUBDIR cpp
)
FetchContent_MakeAvailable(fory)
target_link_libraries(my_app PRIVATE fory::serialization)

Bazel:

# MODULE.bazel
bazel_dep(name = "fory", version = "1.2.0")
git_override(module_name = "fory", remote = "https://github.com/apache/fory.git", commit = "v1.2.0")

# BUILD
deps = ["@fory//cpp/fory/serialization:fory_serialization"]

When building C++ with MSVC, enable the conforming preprocessor option /Zc:preprocessor; see the C++ installation guide for setup details.

See the C++ installation guide for complete CMake, Bazel, and source-build details.

Go

go get github.com/apache/fory/go/fory

JavaScript/TypeScript

npm install @apache-fory/core

For the Node.js string fast path:

npm install @apache-fory/core @apache-fory/hps

C#

dotnet add package Apache.Fory --version 1.2.0

Dart

dart pub add fory:^1.2.0
dart pub add dev:build_runner

Swift

Add Fory to Package.swift:

dependencies: [
  .package(url: "https://github.com/apache/fory.git", exact: "1.2.0")
],
targets: [
  .target(
    name: "YourTarget",
    dependencies: [.product(name: "Fory", package: "fory")]
  )
]

See the Swift guide for generated serializer setup.

Development From Source

See docs/DEVELOPMENT.md.

Snapshots for Java, Scala, and Kotlin are available from https://repository.apache.org/snapshots/ with the matching -SNAPSHOT version.

Choose Serialization Mode

Mode Use it when Start here
Xlang mode Data crosses language boundaries Cross-language guide
Native mode Producer and consumer are in the same language Language guide
Row format You need random field access or analytics-style partial reads Row format spec

For Java, Scala, Kotlin, Python, C++, Go, and Rust, use native mode for same-language traffic. It avoids xlang's cross-language type mapping and metadata constraints, stays closer to each language's native type system, and supports broader language-specific object graphs. Use it when both producer and consumer are in the same language family and you want the native object model rather than a portable cross-language schema.

For Java/JVM-only systems, native mode is the replacement path for JDK serialization, Kryo, FST, Hessian, and Java-only Protocol Buffers payloads. For Python-only systems, native mode is the replacement path for pickle and cloudpickle.

Compatible mode is Fory's schema-evolution mode. It writes the metadata readers and writers need to tolerate schema differences. It is the default for xlang mode and native mode in implementations that expose the option.

Use compatible mode when services deploy independently or when fields may be added or deleted over time. Set compatible mode to false only when every reader and writer always uses the same schema and you want faster serialization and smaller size. For xlang payloads, set compatible mode to false only after verifying that every language uses the same schema, or when native types are generated from Fory schema IDL.

For xlang, all peers must agree on type identity. Name-based registration is easier to read in examples. Numeric IDs are smaller and faster, but they require coordination across every reader and writer.

Cross-Language Serialization

Xlang mode writes the cross-language Fory wire format. Bytes produced by one language implementation can be read by another when every peer uses the same type identity, compatible mode setting, and field schema.

Java

import org.apache.fory.Fory;

public class Example {
  public static class Person {
    public String name;
    public int age;
  }

  public static void main(String[] args) {
    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);
    Person decoded = (Person) fory.deserialize(bytes);
    System.out.println(decoded.name);
  }
}

Python

from dataclasses import dataclass

import pyfory

@dataclass
class Person:
    name: str
    age: pyfory.Int32

fory = pyfory.Fory(xlang=True)
fory.register_type(Person, name="example.Person")

data = fory.serialize(Person("Alice", 30))
person = fory.deserialize(data)
print(person.name)

Go

package main

import (
    "fmt"

    "github.com/apache/fory/go/fory"
)

type Person struct {
    Name string
    Age  int32
}

func main() {
    f := fory.New(fory.WithXlang(true))
    if err := f.RegisterStructByName(Person{}, "example.Person"); err != nil {
        panic(err)
    }

    data, _ := f.Serialize(&Person{Name: "Alice", Age: 30})
    var person Person
    if err := f.Deserialize(data, &person); err != nil {
        panic(err)
    }
    fmt.Println(person.Name)
}

Rust

use fory::{Error, Fory, ForyStruct};

#[derive(ForyStruct, Debug, PartialEq)]
struct Person {
    name: String,
    age: i32,
}

fn main() -> Result<(), Error> {
    let mut fory = Fory::builder().xlang(true).build();
    fory.register_by_name::<Person>("example.Person")?;

    let bytes = fory.serialize(&Person {
        name: "Alice".to_string(),
        age: 30,
    })?;
    let person: Person = fory.deserialize(&bytes)?;
    println!("{}", person.name);
    Ok(())
}

C++

#include "fory/serialization/fory.h"
#include <cstdint>
#include <iostream>
#include <string>

using namespace fory::serialization;

struct Person {
  std::string name;
  int32_t age;
};
FORY_STRUCT(Person, name, age);

int main() {
  auto fory = Fory::builder().xlang(true).build();
  fory.register_struct<Person>("example.Person");

  auto bytes = fory.serialize(Person{"Alice", 30}).value();
  Person person = fory.deserialize<Person>(bytes).value();
  std::cout << person.name << std::endl;
}

JavaScript/TypeScript

import Fory, { Type } from "@apache-fory/core";

const personType = Type.struct(
  { typeName: "example.Person" },
  {
    name: Type.string(),
    age: Type.int32(),
  },
);

const fory = new Fory();
const { serialize, deserialize } = fory.register(personType);

const bytes = serialize({ name: "Alice", age: 30 });
const person = deserialize(bytes);
console.log(person.name);

C#

```csharp using Apache.Fory;

[ForyStruct] public sealed class Person { public string Name { get; set; } = string.Em

Extension points exported contracts — how you extend this code

ForyDefault (Interface)
Trait for creating default values during Fory deserialization. `ForyDefault` is similar to Rust's standard `Default` tr [43 …
rust/fory-core/src/serializer/core.rs
Serializer (Interface)
Serializer is the unified interface for all serialization. It provides reflect.Value-based API for efficient serializati [85 …
go/fory/serializer.go
ForyCopyable (Interface)
Fory copy interface. Customize the copy method of the class @param custom copy interface object [112 implementers]
java/fory-core/src/main/java/org/apache/fory/ForyCopyable.java
OptionalCustomType (Interface)
(no doc) [13 implementers]
java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
NestedInterface (Interface)
(no doc) [13 implementers]
java/fory-latest-jdk-tests/src/test/java/org/apache/fory/integration_tests/RecordRowTest.java
BenchmarkCase (Interface)
(no doc) [6 implementers]
benchmarks/rust/src/data.rs
TypeConfig (Interface)
A trait that defines associated types, similar to OpenRaft's RaftTypeConfig [1 implementers]
rust/tests/tests/test_associated_types.rs
CollectionBuilder (Interface)
* Collection builder interface adapts an iterable to allow incremental build by the fory protocol. */
kotlin/fory-kotlin/src/main/kotlin/org/apache/fory/serializer/kotlin/CollectionBuilder.kt

Core symbols most depended-on inside this repo

append
called by 5007
python/pyfory/format/columnar.py
unwrap
called by 1909
java/fory-core/src/main/java/org/apache/fory/reflect/TypeRef.java
get
called by 1667
java/fory-core/src/main/java/org/apache/fory/collection/Cache.java
serialize
called by 1324
java/fory-core/src/main/java/org/apache/fory/BaseFory.java
add
called by 1055
java/fory-core/src/test/java/org/apache/fory/platform/internal/JDKAccessTest.java
deserialize
called by 1042
java/fory-core/src/main/java/org/apache/fory/BaseFory.java
error
called by 990
java/fory-core/src/main/java/org/apache/fory/logging/Logger.java
withXlang
called by 959
java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java

Shape

Method 20,089
Function 5,098
Class 4,563
Struct 311
Enum 195
Interface 140
TypeAlias 19
FuncType 1

Languages

Java46%
Python15%
C++10%
Rust9%
Go8%
C#6%

Modules by API surface

java/fory-core/src/main/java25/org/apache/fory/memory/MemoryBuffer.java264 symbols
java/fory-core/src/main/java/org/apache/fory/memory/MemoryBuffer.java236 symbols
java/fory-core/src/main/java/org/apache/fory/codegen/Expression.java220 symbols
csharp/tests/Fory.Tests/ForyRuntimeTests.cs181 symbols
python/pyfory/tests/test_policy.py175 symbols
java/fory-core/src/test/java/org/apache/fory/serializer/ObjectStreamSerializerTest.java170 symbols
cpp/fory/serialization/struct_serializer.h165 symbols
java/fory-core/src/test/java/org/apache/fory/xlang/XlangTestBase.java162 symbols
cpp/fory/serialization/xlang_test_main.cc159 symbols
java/fory-core/src/main/java/org/apache/fory/resolver/TypeResolver.java158 symbols
java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecBuilder.java149 symbols
java/fory-core/src/main/java/org/apache/fory/memory/MemoryOps.java147 symbols

For agents

$ claude mcp add fory \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact