Last active
August 13, 2021 00:26
-
-
Save cgiosy/e13a8bed148647efc48e78f00b8445f3 to your computer and use it in GitHub Desktop.
JSON decycle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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