手写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]'));
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容