Last active
June 28, 2023 01:47
-
-
Save xcatliu/521de80693804928432e0a5f2693ba96 to your computer and use it in GitHub Desktop.
Serialize any object, stringify it, print to console, and write to clipboard
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
/** | |
* 序列化任意一个对象 | |
*/ | |
function serialize(obj, options = {}) { | |
const { | |
space, | |
useCircularPath, | |
removeFunction, | |
removeCircular, | |
removeNull, | |
removeUndefined, | |
removeEmpty, | |
pathFilter, | |
printToConsole, | |
copyToClipboard, | |
} = { | |
space: 0, | |
useCircularPath: true, | |
removeFunction: false, | |
removeCircular: false, | |
removeNull: false, | |
removeUndefined: false, | |
removeEmpty: false, | |
pathFilter: undefined, | |
printToConsole: true, | |
copyToClipboard: true, | |
...options, | |
}; | |
/** 换成对象的路径,方便后续检查是否存在循环引用 */ | |
const objMap = new Map(); | |
/** | |
* 将一个对象转换成可以安全 stringify 的对象 | |
*/ | |
function safe(obj, pathPrefix = '$root') { | |
if (obj === null) { | |
if (removeNull) { | |
return '$remove'; | |
} | |
return null; | |
} | |
if (obj === undefined) { | |
if (removeUndefined) { | |
return '$remove'; | |
} | |
return undefined; | |
} | |
if (typeof obj === 'function') { | |
if (removeFunction) { | |
return '$remove'; | |
} | |
return '$function'; | |
} | |
// 产生了循环引用 | |
if (objMap.has(obj)) { | |
if (removeCircular) { | |
return '$remove'; | |
} | |
if (useCircularPath) { | |
return objMap.get(obj); | |
} | |
return '$circular'; | |
} | |
// 如果是对象或数组,则缓存到 objMap 中,方便后续检查是否存在循环引用 | |
if (Array.isArray(obj)) { | |
objMap.set(obj, pathPrefix); | |
let result = []; | |
obj.forEach((value, index) => { | |
const newValue = safe(value, `${pathPrefix}[${index}]`); | |
if (newValue === '$remove') { | |
// should be removed | |
} else { | |
result.push(newValue); | |
} | |
}); | |
if (removeEmpty && result.length === 0) { | |
return '$remove'; | |
} | |
return result; | |
} | |
if (typeof obj === 'object') { | |
objMap.set(obj, pathPrefix); | |
let result = {}; | |
Object.entries(obj).forEach(([key, value]) => { | |
const newValue = safe(value, `${pathPrefix}.${key}`); | |
if (newValue === '$remove') { | |
// should be removed | |
} else { | |
result[key] = newValue; | |
} | |
}); | |
if (removeEmpty && Object.keys(result).length === 0) { | |
return '$remove'; | |
} | |
return result; | |
} | |
if (pathFilter && pathFilter(pathPrefix)) { | |
return '$remove'; | |
} | |
// 其他情况直接返回 | |
return obj; | |
} | |
let safeObj = safe(obj); | |
let stringResult = ''; | |
if (space === 0) { | |
stringResult = JSON.stringify(safeObj); | |
} else { | |
stringResult = JSON.stringify(safeObj, null, space); | |
} | |
if (printToConsole) { | |
console.log(stringResult); | |
} | |
if (copyToClipboard) { | |
copy(stringResult); | |
} | |
return stringResult; | |
} | |
function copy(text) { | |
const textarea = document.createElement("textarea"); | |
textarea.value = text; | |
document.body.appendChild(textarea); | |
textarea.select(); | |
document.execCommand("copy"); | |
document.body.removeChild(textarea); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment