Skip to main content
Version: dev

JavaScript Serialization Guide

Apache Fory JavaScript lets you serialize JavaScript and TypeScript objects to bytes and deserialize them back — including across services written in Java, Python, Go, Rust, Swift, and other Fory-supported languages.

Why Fory JavaScript?

  • Cross-language: serialize in JavaScript, deserialize in Java, Python, Go, and more without writing glue code
  • Fast: serializer code is generated and cached the first time you register a schema, not on every call
  • Reference-aware: shared references and circular object graphs are supported when enabled
  • Explicit schemas: field types, nullability, and polymorphism are declared once with Type.* builders or TypeScript decorators
  • Safe defaults: configurable depth, binary size, and collection size limits reject unexpectedly large or deep payloads
  • Modern types: bigint, typed arrays, Map, Set, Date, float16, and bfloat16 are supported

Installation

Install the JavaScript packages from npm:

npm install @apache-fory/core

Optional Node.js string fast-path support is available through @apache-fory/hps:

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

@apache-fory/hps depends on Node.js 20+ and is optional. If it is unavailable, Fory still works correctly; omit hps from the configuration.

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);
// { id: 1n, name: 'Alice', age: 30 }

How it works

Fory is schema-driven. You describe the shape of your data once with Type.* builders (or TypeScript decorators), then call fory.register(schema). This returns a { serialize, deserialize } pair that is fast to call repeatedly.

// 1. Define the schema
const personType = Type.struct("example.person", {
name: Type.string(),
email: Type.string().setNullable(true),
});

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

// 3. Use as many times as needed
const bytes = serialize({ name: "Alice", email: null });
const person = deserialize(bytes);

Create one Fory instance per application and reuse it — creating a new one for every request wastes the work of schema registration.

Configuration

import Fory from "@apache-fory/core";
import hps from "@apache-fory/hps";

const fory = new Fory({
ref: true,
compatible: true,
maxDepth: 100,
maxBinarySize: 64 * 1024 * 1024,
maxCollectionSize: 1_000_000,
hps,
});
OptionDefaultDescription
reffalseEnable reference tracking for shared or circular object graphs
compatiblefalseAllow field additions/removals without breaking existing messages
maxDepth50Maximum nesting depth. Must be >= 2. Increase for deeply nested structures
maxBinarySize64 MiBMaximum bytes accepted for any single binary field
maxCollectionSize1_000_000Maximum elements accepted in any list, set, or map
useSliceStringfalseOptional string-reading optimization for Node.js. Leave at default unless benchmarked
hpsunsetOptional fast string helper from @apache-fory/hps (Node.js 20+)
hooks.afterCodeGeneratedunsetCallback to inspect the generated serializer code — useful for debugging

Documentation

TopicDescription
Basic SerializationCore APIs and everyday usage
Type RegistrationNumeric IDs, names, decorators, and schema registration
Supported TypesPrimitive, collection, time, enum, and struct mappings
ReferencesShared references and circular object graphs
Schema EvolutionCompatible mode and evolving structs
Cross-LanguageInterop guidance and mapping rules
TroubleshootingCommon issues, limits, and debugging tips