UNPKG

json-decycle

Version:

Stringify and parse cycled reference json

62 lines 1.9 kB
// src/index.ts var isObject = (value) => typeof value === "object" && value != null && !(value instanceof Boolean) && !(value instanceof Date) && !(value instanceof Number) && !(value instanceof RegExp) && !(value instanceof String); var toPointer = (parts) => "#" + parts.map((part) => String(part).replace(/~/g, "~0").replace(/\//g, "~1")).join("/"); var decycle = () => { const paths = /* @__PURE__ */ new WeakMap(); return function replacer(key, value) { if (key !== "$ref" && isObject(value)) { const seen = paths.has(value); if (seen) { return { $ref: toPointer(paths.get(value)) }; } else { paths.set(value, [...paths.get(this) ?? [], key]); } } return value; }; }; function retrocycle() { const parents = /* @__PURE__ */ new WeakMap(); const keys = /* @__PURE__ */ new WeakMap(); const refs = /* @__PURE__ */ new Set(); function dereference(ref) { const parts = ref.$ref.slice(1).split("/"); let key, parent, value = this; for (var i = 0; i < parts.length; i++) { key = parts[i].replace(/~1/g, "/").replace(/~0/g, "~"); value = value[key]; } parent = parents.get(ref); parent[keys.get(ref)] = value; } return function reviver(key, value) { if (key === "$ref") { refs.add(this); } else if (isObject(value)) { var isRoot = key === "" && Object.keys(this).length === 1; if (isRoot) { refs.forEach(dereference, this); } else { parents.set(value, this); keys.set(value, key); } } return value; }; } var extend = (JSON) => { return Object.defineProperties(JSON, { decycle: { value: (object, space) => JSON.stringify(object, decycle(), space) }, retrocycle: { value: (s) => JSON.parse(s, retrocycle()) } }); }; export { decycle, extend, retrocycle }; //# sourceMappingURL=index.js.map