circ-json
Version:
Json (=readable) inspired serializer.
88 lines (84 loc) • 2.76 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
// This is a port of json-decycle. It has a few bug fixes and is in ts.
const isObject = (value) => typeof value === 'object'
&& value != null
&& !(value instanceof Boolean)
&& !(value instanceof Date)
&& !(value instanceof Number)
&& !(value instanceof RegExp)
&& !(value instanceof String);
const toPointer = (parts) => '#' + parts.map(part => String(part).replace(/~/g, '~0').replace(/\//g, '~1')).join('/');
const sym = Symbol('$ref');
function decycle() {
const paths = new WeakMap();
return function replacer(key, value) {
if (key === '$ref' && (typeof value === "string" || (value instanceof String && !value[sym])) && value.startsWith("#"))
return "#" + value;
if (isObject(value)) {
const seen = paths.has(value);
if (seen) {
const $ref = new String(toPointer(paths.get(value)));
$ref[sym] = true;
return { $ref };
}
else {
paths.set(value, [...paths.get(this) ?? [], key]);
}
}
return value;
};
}
function retrocycle() {
const parents = new WeakMap();
const keys = new WeakMap();
const refs = new Set();
/**
* @param {{ $ref: string }} ref
* @this object
*/
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' && typeof value === "string") {
if (value.startsWith("##"))
return value.slice(1);
else if (value.startsWith("#")) {
refs.add(this);
return value;
}
}
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;
};
}
function parse(str) {
if (str === undefined)
return undefined;
return JSON.parse(str, retrocycle());
}
function stringify(obj, space) {
return JSON.stringify(obj, decycle(), space);
}
exports.decycle = decycle;
exports.parse = parse;
exports.retrocycle = retrocycle;
exports.stringify = stringify;
//# sourceMappingURL=circJson.js.map