Skip to content

Instantly share code, notes, and snippets.

@cgiosy
Last active August 13, 2021 00:26
Show Gist options
  • Save cgiosy/e13a8bed148647efc48e78f00b8445f3 to your computer and use it in GitHub Desktop.
Save cgiosy/e13a8bed148647efc48e78f00b8445f3 to your computer and use it in GitHub Desktop.
JSON decycle
const replaceSetMap = (object) => {
if (object) {
if (object.constructor === Set) return [...object];
if (object.constructor === Map) return Object.fromEntries(object);
}
return object;
};
const decycle = (rootObject, { replacer = replaceSetMap, seen = new WeakMap() } = {}) => {
const _decycle = (object, path = "$") => {
if (replacer !== undefined) object = replacer(object);
let ctor;
if (!object || !(ctor = object.constructor) || ctor === Number || ctor === String || ctor === Boolean || ctor === RegExp || ctor === Date || ctor === RegExp || typeof object !== "object") return object;
if (seen.has(object)) return { $ref: seen.get(object) };
seen.set(object, path);
if (ctor === Array) return object.map((value, key) => _decycle(value, `${path}[${key}]`));
const result = { ...object };
for (const key in result) result[key] = _decycle(result[key], `${path}[${JSON.stringify(key)}]`);
return result;
};
return _decycle(rootObject);
};
const stringify = (rootObject, { replacer = replaceSetMap, seen = new WeakMap(), result = "" } = {}) => {
const _stringify = (object, path = "$") => {
if (replacer !== undefined) object = replacer(object);
let ctor;
if (object === undefined) return null; // undefined is not a valid JSON value
if (object === null || !(ctor = object.constructor) || ctor === Number || ctor === String || ctor === Boolean || ctor === RegExp || ctor === Date || ctor === RegExp || typeof object !== "object") {
result += JSON.stringify(object) ?? '"' + object.toString() + '"';
return;
}
if (seen.has(object)) {
result += `{"$ref":${JSON.stringify(seen.get(object))}}`;
return;
}
seen.set(object, path);
if (ctor === Array) {
result += "[";
let first = true;
for (let key = 0; key < object.length; ++key) {
if (first) first = false;
else result += ",";
_stringify(object[key], `${path}[${key}]`);
}
result += "]";
return;
}
result += "{";
let first = true;
for (const key in object) {
const keyStr = JSON.stringify(key);
if (first) first = false;
else result += ",";
result += keyStr;
result += ":";
_stringify(object[key], `${path}[${keyStr}]`);
}
result += "}";
};
_stringify(rootObject);
return result;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment