-
-
Save jupegarnica/4a232d834756a82dc305367d2be65428 to your computer and use it in GitHub Desktop.
This file contains 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 isString = value => typeof value === 'string'; | |
const isSymbol = value => typeof value === 'symbol' | |
const isUndefined = value => typeof value === 'undefined' | |
const isDate = obj => Object.prototype.toString.call(obj) === '[object Date]' | |
const isFunction = obj => Object.prototype.toString.call(obj) === '[object Function]'; | |
const isComplexDataType = value => (typeof value === 'object' || typeof value === 'function') && value !== null; | |
const isValidBasicDataType = value => value !== undefined && !isSymbol(value); | |
const isValidObj = obj => Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Object]'; | |
const isInfinity = value => value === Infinity || value === -Infinity | |
// Symbol,undefined,function in array will become null | |
// Infinity,NaN will also become null | |
const processSpecialValueInArray = value => | |
isSymbol(value) || isFunction(value) || isUndefined(value) || isInfinity(value) || isNaN(value) ? null : value; | |
// Handling property values according to JSON specification | |
const processValue = value => { | |
if (isInfinity(value) || isNaN(value)) { | |
return null | |
} | |
if (isString(value)) { | |
return `"${value}"` | |
} | |
return value | |
}; | |
// obj.loop = obj | |
const jsonStringify = (function () { | |
// Closure + WeakMap prevent circular references | |
let wp = new WeakMap(); | |
//It is the function in the closure that recursively calls jsonstrify, not the jsonstrify function declared by const | |
return function jsonStringify(obj) { | |
if (wp.get(obj)) throw new TypeError('Converting circular structure to JSON'); | |
let res = ""; | |
if (isComplexDataType(obj)) { | |
if (obj.toJSON) return obj.toJSON; | |
if (!isValidObj(obj)) { | |
return | |
} | |
wp.set(obj, obj); | |
if (Array.isArray(obj)) { | |
res += "["; | |
let temp = []; | |
obj.forEach((value) => { | |
temp.push( | |
isComplexDataType(value) && !isFunction(value) ? | |
jsonStringify(value) : | |
`${processSpecialValueInArray(value, true)}` | |
) | |
}); | |
res += `${temp.join(',')}]` | |
} else { | |
res += "{"; | |
let temp = []; | |
Object.keys(obj).forEach((key) => { | |
if (isComplexDataType(obj[key])) { | |
if (isValidObj(obj[key])) { | |
temp.push(`"${key}":${jsonStringify(obj[key])}`) | |
} else if (isDate(obj[key])) { | |
temp.push(`"${key}":"${obj[key].toISOString()}"`) | |
} else if (!isFunction(obj[key])) { | |
temp.push(`"${key}":{}`) | |
} | |
} else if (isValidBasicDataType(obj[key])) { | |
temp.push(`"${key}":${processValue(obj[key])}`) | |
} | |
}); | |
res += `${temp.join(',')}}` | |
} | |
} else if (isSymbol(obj)) { | |
return | |
} else { | |
return obj | |
} | |
return res | |
} | |
})(); | |
// example | |
let s = Symbol('s') | |
let obj = { | |
str: "123", | |
arr: [1, {e: 1}, s, () => { | |
}, undefined,Infinity,NaN], | |
obj: {a: 1}, | |
Infinity: -Infinity, | |
nan: NaN, | |
undef: undefined, | |
symbol: s, | |
date: new Date(), | |
reg: /123/g, | |
func: () => { | |
}, | |
dom: document.querySelector('body'), | |
}; | |
console.log(jsonStringify(obj)); | |
console.log(JSON.stringify(obj)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment