Skip to main content
Version: 0.17

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

Cross-Language 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.