An open API service indexing awesome lists of open source software.

https://github.com/apache/fory

A blazingly fast multi-language serialization framework for idiomatic domain objects, schema IDL, and cross-language data exchange.
https://github.com/apache/fory

compression cpp cross-language encoding fast golang hacktoberfest java javascript jit lightning marshalling multiple-language persistence python rpc rust serialization transfer zero-copy

Last synced: 14 days ago
JSON representation

A blazingly fast multi-language serialization framework for idiomatic domain objects, schema IDL, and cross-language data exchange.

Awesome Lists containing this project

README

          


Apache Fory logo

[![Build Status](https://img.shields.io/github/actions/workflow/status/apache/fory/ci.yml?branch=main&style=for-the-badge&label=GITHUB%20ACTIONS&logo=github)](https://github.com/apache/fory/actions/workflows/ci.yml)
[![Slack Channel](https://img.shields.io/badge/slack-join-3f0e40?logo=slack&style=for-the-badge)](https://join.slack.com/t/fory-project/shared_invite/zt-36g0qouzm-kcQSvV_dtfbtBKHRwT5gsw)
[![X](https://img.shields.io/badge/@ApacheFory-follow-blue?logo=x&style=for-the-badge)](https://x.com/ApacheFory)
[![Maven Version](https://img.shields.io/maven-central/v/org.apache.fory/fory-core?style=for-the-badge)](https://search.maven.org/#search|gav|1|g:"org.apache.fory"%20AND%20a:"fory-core")
[![Crates.io](https://img.shields.io/crates/v/fory.svg?style=for-the-badge)](https://crates.io/crates/fory)
[![PyPI](https://img.shields.io/pypi/v/pyfory.svg?logo=PyPI&style=for-the-badge)](https://pypi.org/project/pyfory/)
[![npm](https://img.shields.io/npm/v/%40apache-fory%2Fcore?logo=npm&style=for-the-badge)](https://www.npmjs.com/package/@apache-fory/core)
[![NuGet](https://img.shields.io/nuget/v/Apache.Fory?logo=nuget&style=for-the-badge)](https://www.nuget.org/packages/Apache.Fory)
[![pub.dev](https://img.shields.io/pub/v/fory?logo=dart&style=for-the-badge)](https://pub.dev/packages/fory)

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

## Why Fory

Fory is built for fast, compact serialization across languages and runtimes. 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, partial reads, and Arrow
integration.
- **Optimized Runtimes**: Java JIT serializers and generated/static serializers
in other runtimes 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, 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 runtime-specific results
across supported languages.

**Java** [Benchmarks](docs/benchmarks/java)

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](benchmarks/python)


Python serialization throughput

**Rust** [Benchmarks](benchmarks/rust)


Rust serialization throughput

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

**C++** [Benchmarks](benchmarks/cpp)


C++ serialization throughput

**Go** [Benchmarks](benchmarks/go)


Go serialization throughput

**JavaScript/TypeScript** [Benchmarks](docs/benchmarks/javascript)


JavaScript serialization throughput

**C#** [Benchmarks](docs/benchmarks/csharp)


C# serialization throughput

**Swift** [Benchmarks](docs/benchmarks/swift)


Swift serialization throughput

**Dart** [Benchmarks](docs/benchmarks/dart)


Dart serialization throughput

## Installation

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

**Java**

Maven:

```xml

org.apache.fory
fory-core
1.0.0

```

Gradle:

```gradle
implementation "org.apache.fory:fory-core:1.0.0"
```

**Scala**

sbt:

```scala
libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.0.0"
```

**Kotlin**

Gradle:

```kotlin
implementation("org.apache.fory:fory-kotlin:1.0.0")
```

Maven:

```xml

org.apache.fory
fory-kotlin
1.0.0

```

**Python**

```bash
pip install pyfory
```

For row-format support:

```bash
pip install "pyfory[format]"
```

**Rust**

`Cargo.toml`:

```toml
[dependencies]
fory = "1.0.0"
```

**C++**

CMake:

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

Bazel:

```bazel
# MODULE.bazel
bazel_dep(name = "fory", version = "1.0.0")
git_override(module_name = "fory", remote = "https://github.com/apache/fory.git", commit = "v1.0.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](https://fory.apache.org/docs/guide/cpp/#installation)
for complete CMake, Bazel, and source-build details.

**Go**

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

**JavaScript/TypeScript**

```bash
npm install @apache-fory/core
```

For the Node.js string fast path:

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

**C#**

```bash
dotnet add package Apache.Fory --version 1.0.0
```

**Dart**

```bash
dart pub add fory:^1.0.0
dart pub add dev:build_runner
```

**Swift**

Add Fory to `Package.swift`:

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

See the [Swift guide](https://fory.apache.org/docs/guide/swift/) for generated
serializer setup.

**Development From Source**

See [docs/DEVELOPMENT.md](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](docs/guide/xlang) |
| Native mode | Producer and consumer are in the same language | Language guide for your runtime |
| Row format | You need random field access or analytics-style partial reads | [Row format spec](docs/specification/row_format_spec.md) |

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 runtime's native type system, and
supports broader language-specific object graphs. Use it when both producer and
consumer are in the same runtime 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. Xlang mode enables compatible
mode by default to better handle differences between language type systems.
Native mode keeps it off by default for smaller payloads and higher throughput.

Use compatible mode when services deploy independently or when fields may be
added or deleted over time. Use schema-consistent mode when writer and reader
schemas deploy together and you want the smallest payloads.

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
runtime can be read by another when the runtimes use the same type identity,
compatible mode setting, and field schema.

**Java**

```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**

```python
from dataclasses import dataclass

import pyfory

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

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

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

**Go**

```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**

```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::("example", "Person")?;

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

**C++**

```cpp
#include "fory/serialization/fory.h"
#include
#include
#include

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("example", "Person");

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

**JavaScript/TypeScript**

```ts
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;

[ForyObject]
public sealed class Person
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
}

Fory fory = Fory.Builder().Build();
fory.Register("example", "Person");

byte[] bytes = fory.Serialize(new Person { Name = "Alice", Age = 30 });
Person person = fory.Deserialize(bytes);
Console.WriteLine(person.Name);
```

C# always writes the xlang frame header, so there is no separate xlang builder
flag.

**Dart**

```dart
import 'package:fory/fory.dart';

part 'person.fory.dart';

@ForyStruct()
class Person {
Person();

String name = '';

@ForyField(type: Int32Type())
int age = 0;
}

void main() {
final fory = Fory();
PersonFory.register(
fory,
Person,
namespace: 'example',
typeName: 'Person',
);

final bytes = fory.serialize(Person()
..name = 'Alice'
..age = 30);
final person = fory.deserialize(bytes);
print(person.name);
}
```

Dart uses the xlang wire format directly. Generate the companion file before
running:

```bash
dart run build_runner build --delete-conflicting-outputs
```

**Swift**

```swift
import Fory

@ForyStruct
struct Person {
var name: String = ""
var age: Int32 = 0
}

let fory = Fory()
try fory.register(Person.self, namespace: "example", name: "Person")

let bytes = try fory.serialize(Person(name: "Alice", age: 30))
let person: Person = try fory.deserialize(bytes)
print(person.name)
```

**Scala**

```scala
import org.apache.fory.scala.ForyScala

case class Person(name: String, age: Int)

val fory = ForyScala.builder().withXlang(true).build()
fory.register(classOf[Person], "example.Person")

val bytes = fory.serialize(Person("Alice", 30))
val person = fory.deserialize(bytes).asInstanceOf[Person]
println(person.name)
```

**Kotlin**

```kotlin
import org.apache.fory.kotlin.ForyKotlin

data class Person(val name: String, val age: Int)

fun main() {
val fory = ForyKotlin.builder().withXlang(true).build()
fory.register(Person::class.java, "example.Person")

val bytes = fory.serialize(Person("Alice", 30))
val person = fory.deserialize(bytes) as Person
println(person.name)
}
```

For shared/circular references, polymorphism, numeric IDs versus names, and
type-mapping rules, see the [cross-language guide](docs/guide/xlang) and
[type mapping specification](docs/specification/xlang_type_mapping.md).

## Native Serialization

Use native mode when the writer and reader are in the same language. It is
optimized for each runtime's native type system and can cover language-specific
types, object graphs, and framework-replacement cases that xlang mode keeps out
of the portable wire format. The languages below expose an explicit
`xlang=false` or native-mode setting; runtimes without that switch stay on their
documented default path.

Choose Java native mode for Java/JVM-only replacements of JDK serialization,
Kryo, FST, Hessian, or Java-only Protocol Buffers payloads. Choose Python native
mode when replacing pickle or cloudpickle for Python-only payloads.

Keep class/type registration enabled for untrusted input. See the language guides
for runtime-specific security and compatibility settings.

**Java**

```java
Fory fory = Fory.builder()
.withXlang(false)
.requireClassRegistration(true)
.build();
// Register, serialize, and deserialize as in the xlang example above.
```

**Python**

```python
fory = pyfory.Fory(xlang=False, ref=True)
# Register, serialize, and deserialize as in the xlang example above.
```

**Go**

```go
f := fory.New(fory.WithXlang(false))
// Register, serialize, and deserialize as in the xlang example above.
```

**Rust**

```rust
let mut fory = Fory::builder().xlang(false).build();
// Register, serialize, and deserialize as in the xlang example above.
```

**C++**

```cpp
auto fory = Fory::builder().xlang(false).build();
// Register, serialize, and deserialize as in the xlang example above.
```

**Scala**

```scala
import org.apache.fory.scala.ForyScala

val fory = ForyScala.builder()
.withXlang(false)
.requireClassRegistration(true)
.build()
// Register, serialize, and deserialize as in the xlang example above.
```

**Kotlin**

```kotlin
import org.apache.fory.kotlin.ForyKotlin

val fory = ForyKotlin.builder()
.withXlang(false)
.requireClassRegistration(true)
.build()
// Register, serialize, and deserialize as in the xlang example above.
```

## Schema IDL

Fory IDL is Fory's schema language for shared data models. It supports
references, nullable fields, lists, maps, arrays, enums, messages, and unions,
and generates native data structures for supported languages. Use it when
multiple languages need one shared contract.

```protobuf
package tree;

message TreeNode {
string id = 1;
string name = 2;

list children = 3;
ref(weak=true) TreeNode parent = 4; // back-pointer
}
```

See the [Fory IDL and compiler guide](https://fory.apache.org/docs/compiler).

## Row Format

Row format is for random access and partial reads. These examples encode an
object with an integer array field, then read one array element from the binary
row without rebuilding the object.

**Python**

```python
from dataclasses import dataclass
from typing import List

import pyfory

@dataclass
class User:
id: pyfory.Int32
name: str
scores: List[pyfory.Int32]

encoder = pyfory.encoder(User)
binary = encoder.to_row(User(1, "Alice", [98, 100, 95])).to_bytes()

row = pyfory.RowData(encoder.schema, binary)
print(row.name)
print(row.scores[1])
```

**Java**

```java
public class User {
public int id;
public String name;
public int[] scores;
}

RowEncoder encoder = Encoders.bean(User.class);

User user = new User();
user.id = 1;
user.name = "Alice";
user.scores = new int[] {98, 100, 95};

BinaryRow row = encoder.toRow(user);

Schema schema = encoder.schema();
Schema.StringField nameField = schema.stringField("name");
Schema.ArrayField scoresField = schema.arrayField("scores");

String name = nameField.get(row);
ArrayData scores = scoresField.get(row);
int secondScore = scores.getInt32(1);
```

For Java imports, nested structs, arrays/maps, Arrow integration, and partial
deserialization, see the
[Java row-format guide](https://fory.apache.org/docs/guide/java/row_format), the
[Python row-format guide](docs/guide/python/row-format.md), and the
[row-format specification](docs/specification/row_format_spec.md).

## Documentation

**User Guides**

| Guide | Source | Website |
| --------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------- |
| Java | [docs/guide/java](docs/guide/java) | [View](https://fory.apache.org/docs/guide/java/) |
| Python | [docs/guide/python](docs/guide/python) | [View](https://fory.apache.org/docs/guide/python/) |
| Rust | [docs/guide/rust](docs/guide/rust) | [View](https://fory.apache.org/docs/guide/rust/) |
| C++ | [docs/guide/cpp](docs/guide/cpp) | [View](https://fory.apache.org/docs/guide/cpp/) |
| Go | [docs/guide/go](docs/guide/go) | [View](https://fory.apache.org/docs/guide/go/) |
| JavaScript/TypeScript | [docs/guide/javascript](docs/guide/javascript) | [View](https://fory.apache.org/docs/guide/javascript/) |
| C# | [docs/guide/csharp](docs/guide/csharp) | [View](https://fory.apache.org/docs/guide/csharp/) |
| Swift | [docs/guide/swift](docs/guide/swift) | [View](https://fory.apache.org/docs/guide/swift/) |
| Dart | [docs/guide/dart](docs/guide/dart) | [View](https://fory.apache.org/docs/guide/dart/) |
| Scala | [docs/guide/scala](docs/guide/scala) | [View](https://fory.apache.org/docs/guide/scala/) |
| Kotlin | [docs/guide/kotlin](docs/guide/kotlin) | [View](https://fory.apache.org/docs/guide/kotlin/) |
| Cross-language xlang | [docs/guide/xlang](docs/guide/xlang) | [View](https://fory.apache.org/docs/guide/xlang/) |
| Schema IDL/compiler | [docs/compiler](docs/compiler) | [View](https://fory.apache.org/docs/compiler/) |
| GraalVM native image | [docs/guide/java/graalvm-support.md](docs/guide/java/graalvm-support.md) | [View](https://fory.apache.org/docs/guide/java/graalvm_support) |
| Development | [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) | [View](docs/DEVELOPMENT.md) |

**Specifications**

| Specification | Source | Website |
| ---------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Xlang serialization | [xlang_serialization_spec.md](docs/specification/xlang_serialization_spec.md) | [View](https://fory.apache.org/docs/specification/xlang_serialization_spec) |
| Java serialization | [java_serialization_spec.md](docs/specification/java_serialization_spec.md) | [View](https://fory.apache.org/docs/specification/java_serialization_spec) |
| Row format | [row_format_spec.md](docs/specification/row_format_spec.md) | [View](https://fory.apache.org/docs/specification/row_format_spec) |
| Cross-language mapping | [xlang_type_mapping.md](docs/specification/xlang_type_mapping.md) | [View](https://fory.apache.org/docs/specification/xlang_type_mapping) |

## Community

- [Slack workspace](https://join.slack.com/t/fory-project/shared_invite/zt-36g0qouzm-kcQSvV_dtfbtBKHRwT5gsw)
- [@ApacheFory on X](https://x.com/ApacheFory)
- [GitHub issues](https://github.com/apache/fory/issues)
- Apache Fory mailing lists for development discussion

## Contributing

Read [CONTRIBUTING.md](CONTRIBUTING.md) and
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) before sending pull requests. Bug
reports, docs fixes, tests, benchmarks, and runtime improvements are welcome.

## License

Apache Fory™ is licensed under the [Apache License 2.0](LICENSE).