手写JSON.stringfy() 和 JSON.parse()

啊啊啊啊啊我太菜了我要秃了,菜鸟前端少女自己写的可能会有隐藏bug,请谨慎阅读

JSON.stringfy()
function myStringfy(data){
    // 字符串 >>> 自己
    // 数字 >>> 自己
    // undefined >>> 自己 (外面不加引号)
    // null >>> 自己
    // function >>> undefined (外面不加引号)
    // 数组 >>> 用逗号分隔 如果某项为undefined 该项处记录为null
    // 对象 >>> key 用双引号包起来, 各属性逗号分隔 筛选掉undefined
    const myStringfyFunc = (data) => {
        if( data === null || data === undefined || typeof(data) === 'string' || typeof(data) === 'number' ){
            return data;
        } else if( typeof(data) === 'function' ){
            return undefined;
        } else if(typeof(data) === 'object'){
            if(Array.isArray(data)){ // 数组
                return `[${
                    data.map(item=>{
                        if(myStringfyFunc(item) === undefined || item === null) return 'null';
                        else return myStringfyFunc(item);
                    }).join(',')
                }]`
            } else { // 对象
                let arr = [];
                for(let key in data){
                    if(myStringfyFunc(data[key]) !== undefined){
                        arr.push(`"${key}":${myStringfyFunc(data[key])}`);
                    }
                }
                return `{${arr.join(',')}}`
            }
        } else {
            return new Exception('UNKNOWN TYPE!')
        }
    }

    if(data === undefined || typeof(data) === 'function'){
        return myStringfyFunc(data);
    } else if(typeof(data) === 'string'){
        return `"${myStringfyFunc(data)}"`
    } else {
        return `${myStringfyFunc(data)}`
    }
}

测试方法

function test(data){
    const res1 = JSON.stringify(data);
    const res2 = myStringfy(data);
    return {
        passed: res1 === res2, // 对于多层嵌套的引用类型无法正确判断
        input: data,
        correct: res1,
        yours: res2,
    }
}
// console.log(test());
// console.log(test(''));
// console.log(test('123'));
// console.log(test(0));
// console.log(test(1111));
// console.log(test({a:111,b:null,c:undefined,d:function(){}}));
// console.log(test([1,2,null,undefined,function(){}]));
// console.log(test(null));
// console.log(test(undefined));
JSON.parse()
function myParse(str){
    const err = ()=>{ throw new Error('WRONG JSON!') }
    const indexStr = (str, sub)=>{
        for(let i=0; i< str.length; i++){
            if(str.substr(i,sub.length) === sub){
                return i;
            }
        }
        return -1;
    }
    const charStrCount = (str, char) => {
        let count = 0;
        for(let i = 0; i< str.length;i++){
            if(str.charAt(i) === char) count++;
        }
        return count;
    }
    const letfPunc = ['[','{'];
    // null >>> null
    // number >>> 自己
    // 非空字符串 >>> ↓
    // 其他 >>> 报错

    // ----非空字符串----
    // 数字 (Number(a)!==NAN)
    // 字符串 前后都是 ""
    // null === 'null'
    // 数组(过程中校验) [开头 ]结尾
    // 对象(过程中校验) {开头 }结尾

    if (str === null) return null;
    else if (typeof(str) === 'number') return str;
    else if (typeof(str) === 'string' && str !== ''){
        if(!Number.isNaN(Number(str))) return Number(str);
        else if( str.charAt(0) === '"' && str.charAt(str.length-1) === '"' && charStrCount(str, '"') === 2 ){
            str = str.substring(0,str.length-1).substring(1)
            return str;
        } else if( str === 'null' ) return null;
        else if(str.charAt(0) === '{' && str.charAt(str.length-1) === '}'){ // ----对象----
            str = str.substring(0,str.length-1).substring(1);
            const obj = {};
            let propCount = 0;
            while(str.length>0){
                if(propCount>0){
                    if(str.charAt(0)!==',') err();
                    str = str.substring(1);
                }
                if(str.charAt(0) === '"'){
                    str = str.substring(1);
                    const keyEndIndex = indexStr(str,'"');
                    if(keyEndIndex>=0){
                        const key = str.substring(0,keyEndIndex);
                        str = str.substring(keyEndIndex+1);
                        if(str.charAt(0) === ':'){
                            str = str.substring(1);
                            // value可能是 null || 123 || "string" || [] || {}
                            if(indexStr(str, 'null')===0){ // null
                                obj[key] = null;
                                str = str.substring(4);
                            } else if(Number(str.charAt(0)>0) || (str.charAt(0) === '-'&&Number(str.charAt(1)))){ // number
                                let endIndex = 0;
                                for(let i=1; i<str.length; i++){
                                    if(Number.isNaN(Number(str.charAt(i))) && str.charAt(i)!== '.'){
                                        endIndex = i-1;
                                        break;
                                    }
                                }
                                const value = str.substring(0,endIndex+1);
                                if( typeof(Number(value)) === 'number'){
                                    obj[key] = Number(value);
                                    str = str.substring(endIndex+1);
                                } else {
                                    err();
                                }
                            } else if(str.charAt(0) === '"'){ // string
                                str = str.substring(1);
                                const nextQuoIndex = indexStr(str,'"');
                                if(nextQuoIndex>=0){
                                    obj[key] = str.substring(0,nextQuoIndex);
                                    str = str.substring(nextQuoIndex+1);
                                }
                            } else if(letfPunc.indexOf(str.charAt(0))>=0){  // object || array
                                const temp = [];
                                for(let i=0; i<str.length; i++){
                                    const current = str.charAt(i);
                                    if(letfPunc.indexOf(current)>=0){
                                        temp.push(current);
                                    } else if(current === '}'){
                                        if(temp.pop() !== '{') err();
                                    } else if(current === ']'){
                                        if(temp.pop() !== '[') err();
                                    } else if(current === ','){
                                        if(temp.length === 0) {
                                            obj[key] = myParse(str.substring(0, i));
                                            str = str.substring(i);
                                            break;
                                        }
                                    }
                                    if(i === str.length-1){
                                        if(temp.length === 0){ // 最后一个属性 不会遇到逗号打断
                                            obj[key] = myParse(str);
                                            str = '';
                                        } else err();
                                    }
                                }
                            } else err();
                            propCount++;
                        } else err();
                    } else err()
                } else err();
            }
            return obj;
        } else if(str.charAt(0) === '[' && str.charAt(str.length-1) === ']'){
            str = str.substring(0,str.length-1).substring(1);
            const arr = [];
            while(str.length>0){
                if(arr.length>0){
                    if(str.charAt(0)!==',') err();
                    str = str.substring(1);
                }
                // 数组元素可能是 null || 123 || "string" || [] || {}
                if(indexStr(str, 'null')===0){ // null
                    arr.push(null);
                    str = str.substring(4);
                } else if(Number(str.charAt(0)>0) || (str.charAt(0) === '-'&&Number(str.charAt(1)))){ // number
                    let endIndex = 0;
                    for(let i=1; i<str.length; i++){
                        if(Number.isNaN(Number(str.charAt(i))) && str.charAt(i)!== '.'){
                            endIndex = i-1;
                            break;
                        }
                    }
                    const value = str.substring(0,endIndex+1);
                    if( typeof(Number(value)) === 'number'){
                        arr.push(Number(value))
                        str = str.substring(endIndex+1);
                    } else err();
                } else if(str.charAt(0) === '"'){ // string
                    str = str.substring(1);
                    const nextQuoIndex = indexStr(str,'"');
                    if(nextQuoIndex>=0){
                        arr.push(str.substring(0,nextQuoIndex))
                        str = str.substring(nextQuoIndex+1);
                    }
                } else if(letfPunc.indexOf(str.charAt(0))>=0){  // object || array
                    const temp = [];
                    for(let i=0; i<str.length; i++){
                        const current = str.charAt(i);
                        if(letfPunc.indexOf(current)>=0){
                            temp.push(current);
                        } else if(current === '}'){
                            if(temp.pop() !== '{') err();
                        } else if(current === ']'){
                            if(temp.pop() !== '[') err();
                        } else if(current === ','){
                            if(temp.length === 0) {
                                arr.push(myParse(str.substring(0, i)));
                                str = str.substring(i);
                                break;
                            }
                        }
                        if(i === str.length-1){
                            if(temp.length === 0){ // 最后一个元素 不会遇到逗号打断
                                console.log(str)
                                arr.push(myParse(str));
                                str = '';
                            } else err();
                        }
                    }
                } else err();
            }
            return arr;
        } else {
        };
    } else err();
}

测试程序

function testMyParse(data){
    const res1 = JSON.parse(data);
    const res2 = myParse(data);
    return {
        passed: res1 === res2, // 对于多层嵌套的引用类型无法正确判断
        input: data,
        correct: res1,
        yours: res2,
    }
}
// console.log(testMyParse(null));
// console.log(testMyParse(1));
// console.log(testMyParse(-1.7888));
// console.log(myParse(undefined));
// console.log(myParse(''));
// console.log(myParse('"'));
// console.log(testMyParse('"1233"'));
console.log(testMyParse('{"a":1,"c":null,"d":"dgaiuhgraui","e":[1,2,3,4,{"a":7}]}'));
console.log(testMyParse('[-134,{"b":-78,"c":"hush/..,d,,,:","e":[]},"jduifh{}[{}]",1]'));
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容