Open AnnVoV opened 5 years ago
阅读资料: What you didn’t know about JSON.Stringify https://abdulapopoola.com/2017/02/27/what-you-didnt-know-about-json-stringify/
最主要的原因在于:
Because JSON is a language agnostic format JSON 是通用的文本格式和语言是无关的。如果函数定义也可以stringify的话,那就变得和语言有关了
const getType = (obj) => { return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); }; const getResultFromStack = (stack) => { let result = ''; while (stack.length) { const [key, value] = stack.shift(); const temp = (stack.length === 0) ? `"${key}":${value}` : `"${key}":${value},`; result += temp; } return `{${result}}`; }; //『function|undefined』 const isFunctionOrUndefined = (obj) => /function|undefined/.test(getType(obj)); export default function jsonStringify(obj) { if (obj === null) return 'null'; if (getType(obj) === 'regexp') return '{}'; //『字符串|布尔|数字』直接转换为string类型 if (/string|number|boolean/.test(typeof obj)) { return (typeof obj === 'number') ? obj.toString() : `"${obj.toString()}"`; } //『function|undefined』 不处理 if (isFunctionOrUndefined(obj)) return ''; // 『数组』直接join 为字符串 if (Array.isArray(obj)) return `[${obj.join(',')}]`; if (getType(obj) === 'object') { const stack = []; // 『对象』递归处理 for (const key in obj) { const value = obj[key]; if (isFunctionOrUndefined(value)) { continue; } stack.push([key, jsonStringify(value)]); } return getResultFromStack(stack); } }
递归处理那里,我们其实只要能把key,value 同时存放到队列里,稍后处理就可以了,使用二维数组比较方便
function jsonParseFunction(str) { return new Function(`return ${str}`)(); }
思路来源于下面这篇文章,非常感谢作者: 半小时实现一个JSON 解析器 https://zhuanlan.zhihu.com/p/28049617
并且文章中解释了为什么JSON要设计成这个样子?因为它是容易解析的。读取JSON字符串的字符时,读到特定的开头,我们就能知道我们需要找的是什么值。
let str = ''; let i = 0; const parseObject = () => { i++; const result = {}; while (str[i] !== '}') { // 这个地方一开始没绕过来 const key = parseString(); i++; // 跳过冒号 const value = parseValue(); result[key] = value; if (str[i] === ',') { i++; // 如果是, 说明要继续往下查找 } } i++; return result; }; const parseArray = () => { i++; let result = []; while (str[i] !== ']') { result.push(parseValue()); if (str[i] === ',') { // 跳过逗号 i++; } } i++; return result; }; const parseString = () => { i++; let result = ''; while (str[i] !== '"') { result += str[i]; i++; } i++; return result; }; const parseTrue = () => { const content = str.substr(i, 4); if (content === 'true') { i += 4; return true; } }; const parseFalse = () => { const content = str.substr(i, 5); if (content === 'false') { i += 5; return false; } }; const parseNull = () => { const content = str.substr(i, 4); if (content === 'null') { i += 4; return null; } }; const parseNumber = () => { function isNumberChar(c) { var chars = { '-': true, '+': true, 'e': true, 'E': true, '.': true, }; if (chars[c]) { return true; } if (c >= '0' && c <= '9') { return true; } return false; } let numStr = ''; while (isNumberChar(str[i])) { numStr += str[i++]; } return parseFloat(numStr); }; const parseValue = () => { switch (str[i]) { case '{': { return parseObject(); } case '[': { return parseArray(); } case '"': { return parseString(); } case "t": { return parseTrue(); } case "f": { return parseFalse(); } case "n": { return parseNull(); } default: { return parseNumber(); } } }; export default function jsonParse(orgStr) { str = orgStr.replace(/([^"])(\s*)/g, '$1'); const result = parseValue(); console.log(result); } // --- 测试 --- import jsonParse from './jsonParse'; let str = '{"a":1, "b":true, "c":false, "foo":null, "bar":[1,2,3]}'; jsonParse(str);
JSON.stringify 不能处理哪些类型
阅读资料: What you didn’t know about JSON.Stringify https://abdulapopoola.com/2017/02/27/what-you-didnt-know-about-json-stringify/
最主要的原因在于:
JSON.stringify
递归处理那里,我们其实只要能把key,value 同时存放到队列里,稍后处理就可以了,使用二维数组比较方便
JSON.parse
1.最简单的实现方式, 无脑实现利用new Function
2.写一个简单的针对Json的parser
思路来源于下面这篇文章,非常感谢作者: 半小时实现一个JSON 解析器 https://zhuanlan.zhihu.com/p/28049617
并且文章中解释了为什么JSON要设计成这个样子?因为它是容易解析的。读取JSON字符串的字符时,读到特定的开头,我们就能知道我们需要找的是什么值。