Skip to content

Instantly share code, notes, and snippets.

@xcatliu
Last active June 28, 2023 01:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xcatliu/521de80693804928432e0a5f2693ba96 to your computer and use it in GitHub Desktop.
Save xcatliu/521de80693804928432e0a5f2693ba96 to your computer and use it in GitHub Desktop.
Serialize any object, stringify it, print to console, and write to clipboard
/**
* 序列化任意一个对象
*/
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