跳到主要内容
版本:dev

引用

默认情况下,Fory 将每个值视为独立副本:如果同一个对象出现在两个字段中,它会被序列化两次,反序列化后得到两个独立副本。以下情况应启用引用跟踪:

  • 对象图中的多个位置引用同一个对象实例
  • 数据包含循环结构(例如指向自身的节点)
  • 往返处理后必须保留对象标识

对于普通树形数据,请关闭引用跟踪;它会带来少量开销。

第 1 步:在 Fory 实例上启用引用跟踪

const fory = new Fory({ ref: true });

第 2 步:标记可能具有共享引用或循环引用的字段

对于值可能被共享或形成循环的每个字段,请在字段 Schema 上调用 .setTrackingRef(true)

const nodeType = Type.struct("example.node", {
value: Type.string(),
next: Type.struct("example.node").setNullable(true).setTrackingRef(true),
});

全局标志和字段级标志缺一不可。缺少任意一个都会导致值被复制,而不是作为引用处理。

循环自引用示例

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

共享嵌套引用示例

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

何时启用

以下情况启用引用跟踪:

  • 多个字段复用同一个对象实例
  • 对象图可能形成循环
  • 反序列化后需要保留对象标识

以下情况保持禁用:

  • 数据是普通树形结构
  • 希望获得最低开销
  • 不关心对象标识

跨语言说明

引用跟踪是 Fory 二进制协议的一部分,可以跨语言工作。双方必须都启用引用跟踪,并将相同字段标记为启用引用跟踪,行为才能保持一致。

相关主题