References
By default Fory treats every value as a separate copy — if the same object appears in two fields it gets serialized twice, and after deserialization you get two independent copies. Enable reference tracking when:
- the same object instance is referenced from multiple places in the graph
- your data contains a circular structure (e.g. a node that points to itself)
- object identity must be preserved after a round trip
Leave reference tracking off for plain tree-shaped data; it adds a small overhead.
Step 1: Enable Reference Tracking on the Fory Instance
const fory = new Fory({ ref: true });
Step 2: Mark the Fields That Can Have Shared or Circular References
For each field whose value may be shared or circular, call .setTrackingRef(true) on the field's schema:
const nodeType = Type.struct("example.node", {
value: Type.string(),
next: Type.struct("example.node").setNullable(true).setTrackingRef(true),
});
You need both the global flag and the field-level flag. Missing either one results in values being copied rather than referenced.
Circular self-reference example
import Fory, { Type } from "@apache-fory/core";
const nodeType = Type.struct("example.node", {
name: Type.string(),
selfRef: Type.struct("example.node").setNullable(true).setTrackingRef(true),
});
const fory = new Fory({ ref: true });
const { serialize, deserialize } = fory.register(nodeType);
const node: any = { name: "root", selfRef: null };
node.selfRef = node;
const copy = deserialize(serialize(node));
console.log(copy.selfRef === copy); // true
Shared nested reference example
const innerType = Type.struct(501, {
value: Type.string(),
});
const outerType = Type.struct(502, {
left: Type.struct(501).setNullable(true).setTrackingRef(true),
right: Type.struct(501).setNullable(true).setTrackingRef(true),
});
const fory = new Fory({ ref: true });
const { serialize, deserialize } = fory.register(outerType);
const shared = { value: "same-object" };
const copy = deserialize(serialize({ left: shared, right: shared }));
console.log(copy.left === copy.right); // true
When to enable it
Enable reference tracking when:
- the same object instance is reused in multiple fields
- your graph can be cyclic
- identity preservation matters after deserialization
Leave it disabled when:
- the data is a plain tree
- you want the lowest overhead
- object identity does not matter
Xlang Note
Reference tracking is part of the Fory binary protocol and works across runtimes. Both sides must enable reference tracking and mark the same fields as reference-tracked for the behavior to be consistent.