github apache/fory v0.17.0

7 hours ago

The Apache Fory team is pleased to announce the 0.17.0 release. This is a major release that includes 71 PR from 19 distinct contributors. See the Install Page to learn how to get the libraries for your platform.

JavaScript/NodeJS Serialization: First Release

Apache Fory 0.17.0 marks the first release with official JavaScript/NodeJS
documentation, benchmark coverage, and TypeScript-friendly IDL code generation.
The JavaScript runtime is built for modern Node.js services and TypeScript
codebases, while preserving Fory's cross-language object model, schema-driven
APIs, and optional reference tracking.

Key capabilities:

  • High-performance serialization for JavaScript and TypeScript objects in Node.js
  • Cross-language compatibility with Java, Python, Go, Rust, C#, Swift, and Dart
  • Schema-driven APIs via Type.* builders and TypeScript decorators
  • Optional reference tracking for shared and circular object graphs
  • Compatible mode for schema evolution
  • Configurable depth, binary size, and collection size guardrails
  • JavaScript/TypeScript target support in the Fory IDL/compiler workflow
  • Optional @apache-fory/hps fast string path for Node.js 20+

Quick Start

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

const userType = Type.struct(
  { typeName: "example.user" },
  {
    id: Type.int64(),
    name: Type.string(),
    age: Type.int32(),
  },
);

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

const bytes = serialize({
  id: 1n,
  name: "Alice",
  age: 30,
});

const user = deserialize(bytes);
console.log(user);

JavaScript Benchmarks

Below are throughput results (ops/sec; higher is better) comparing Fory with
Protocol Buffers and JSON across representative data structures.

Datatype Operation Fory TPS Protobuf TPS JSON TPS Fastest
Struct Serialize 8,453,950 1,903,706 3,058,232 fory
Struct Deserialize 9,705,287 8,233,664 3,860,538 fory
Sample Serialize 1,498,391 422,620 744,790 fory
Sample Deserialize 1,918,162 819,010 762,048 fory
MediaContent Serialize 1,293,157 729,497 1,299,908 json
MediaContent Deserialize 1,638,086 1,209,140 921,191 fory
StructList Serialize 3,928,325 495,648 891,810 fory
StructList Deserialize 3,264,827 1,529,744 986,144 fory
SampleList Serialize 355,581 92,741 163,120 fory
SampleList Deserialize 424,916 163,253 162,520 fory
MediaContentList Serialize 286,053 148,977 282,445 fory
MediaContentList Deserialize 376,826 244,622 190,155 fory

Serialized data sizes (bytes):

Datatype Fory Protobuf JSON
Struct 58 61 103
Sample 446 377 724
MediaContent 391 307 596
StructList 184 315 537
SampleList 1980 1900 3642
MediaContentList 1665 1550 3009

Benchmark details: https://github.com/apache/fory/tree/v0.17.0/benchmarks/javascript

Dart Serialization: First Release

Apache Fory 0.17.0 also marks the first release with official Dart
documentation, benchmark coverage, a rebuilt runtime, and Dart IDL support.
The Dart implementation focuses on generated serializers, stable
cross-language type identity, schema evolution, and predictable APIs for
service workloads.

Key capabilities:

  • High-performance Dart serialization with generated code instead of reflection
  • Cross-language compatibility with Java, Python, Go, Rust, C#, Swift, and JavaScript
  • @ForyStruct and @ForyField annotations with build_runner code generation
  • Compatible mode for schema evolution across versions
  • Optional reference tracking for shared and circular object graphs
  • Manual Serializer<T> extension points for advanced or custom types
  • Dart target support in the Fory IDL/compiler workflow

Quick Start

import 'package:fory/fory.dart';

part 'person.fory.dart';

enum Color {
  red,
  blue,
}

@ForyStruct()
class Person {
  Person();

  String name = '';
  Int32 age = Int32(0);
  Color favoriteColor = Color.red;
}

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

  final bytes = fory.serialize(Person()
    ..name = 'Ada'
    ..age = Int32(36)
    ..favoriteColor = Color.blue);
  final roundTrip = fory.deserialize<Person>(bytes);
  print(roundTrip.name);
}

Dart Benchmarks

Below are throughput results (ops/sec; higher is better) comparing Fory with
Protocol Buffers across representative data structures.

Datatype Operation Fory TPS Protobuf TPS Fastest
Struct Serialize 3,989,432 1,884,653 fory (2.12x)
Struct Deserialize 5,828,197 4,199,680 fory (1.39x)
Sample Serialize 1,649,722 500,167 fory (3.30x)
Sample Deserialize 2,060,113 785,109 fory (2.62x)
MediaContent Serialize 800,876 391,235 fory (2.05x)
MediaContent Deserialize 1,315,115 683,533 fory (1.92x)
StructList Serialize 1,456,396 367,506 fory (3.96x)
StructList Deserialize 1,921,006 645,958 fory (2.97x)
SampleList Serialize 411,144 48,508 fory (8.48x)
SampleList Deserialize 464,273 103,558 fory (4.48x)
MediaContentList Serialize 186,870 77,029 fory (2.43x)
MediaContentList Deserialize 330,293 128,215 fory (2.58x)

Serialized data sizes (bytes):

Datatype Fory Protobuf
Struct 58 61
Sample 446 377
MediaContent 365 307
StructList 184 315
SampleList 1980 1900
MediaContentList 1535 1550

Benchmark details: https://github.com/apache/fory/tree/v0.17.0/benchmarks/dart

Highlights

Features

Bug Fix

  • fix(java): Restore compact codec fixed width optimizations by @stevenschlansker in #3478
  • fix(rust): handle panics from fuzz-found edge cases by @utafrali in #3481
  • fix(rust): add error handling logic for std duration; add support for chrono duration by @BaldDemian in #3490
  • fix(compiler): validate rpc request/response types by @retryoos in #3493
  • fix(c++): fix misaligned address access errors detected by UBSan in buffer.h by @BaldDemian in #3479
  • fix(java): finalize codegen config hash on first use by @chaokunyang in #3495
  • fix(rust): fix several panics detected by cargo-fuzz by @BaldDemian in #3483
  • fix(java): handle private final map codegen by @chaokunyang in #3504
  • fix(compiler): repair broken service example and add regression coverage by @VikingDeng in #3505
  • fix(rust): deep clone TypeMeta to prevent UB in concurrent scenarios by @BaldDemian in #3511
  • fix(compiler): fix failed tests in compiler; add compiler CI by @BaldDemian in #3516
  • fix(compiler): allow qualified nested types in FDL rpc signatures by @VikingDeng in #3518
  • fix(java): preserve ConcurrentSkipListSet comparator on copy by @mandrean in #3520
  • test(compiler): add IR validation and codegen tests for gRPC service support by @darius024 in #3528
  • fix(java): Correct resolution of dependent/nested serializers in GraalVM by @rakow in #3532
  • fix(java): fix objectstream serializer async jit and graalvm support by @chaokunyang in #3534
  • ci: fix Bazel cache paths for C++ workflows by @chaokunyang in #3535
  • fix(python): fix wrong calling orders in visit_other by @BaldDemian in #3542
  • fix(js): corrected the float64 array size by @ayush00git in #3541
  • fix(java): configure type checker during build by @chaokunyang in #3550
  • fix(java): auto-select child serializers for sorted containers by @chaokunyang in #3552
  • fix(java): support skip optional sql serializers for java11+ by @chaokunyang in #3553
  • fix(rust): apply consistent pascalcase naming for nested types by @utafrali in #3548
  • fix(javascript): fix flaky javascript idl tests by @chaokunyang in #3565
  • fix(swift): fix swift generated code compile warnings by @chaokunyang in #3566
  • fix(java): add test for previous uncaught regression. by @PiotrDuz in #3573

Other Improvements

New Contributors

Full Changelog: v0.16.0...v0.17.0

Don't miss a new fory release

NewReleases is sending notifications on new releases.