当前位置: 首页 > Web前端 > JavaScript

js栈思路实现解析json字符串的功能

时间:2023-03-27 15:51:24 JavaScript

给定一个json字符串,编写一个函数将其解析为json对象,而无需使用eval、JSON.parse或newFunction。你将如何实施它?json的一个特点就是数组和对象可以相互嵌套,嵌套层数无限,这也是解析json最麻烦的地方。1、思路:栈思路“栈”的特点:先进后出(栈只有一个入口和出口,入口即出口)。现实生活中的对象描述,先放入的乒乓球可以最后取出数据结构:JavaScript中实现“栈”最好的数据结构是数组思想:1.定义两个栈,栈1(stack1)用来存放json对象,栈2(stack2)用于存放json对象的key和value;定义一个变量来存储双引号dabbleQuotCount的个数;定义一个变量来保存截取的字符串2、循环整个json字符串,然后逐个截取json字符字符串的第一个字符判断第一个字符是否以{,[开头。如果以它们开头,则表示遇到了一个对象或数组。这时需要在栈1中加入一个空对象或者空数组,栈2中加入一个空数组,判断第一个字符是否以双引号(")开头,判断是否为double的个数quotes为2,如果为2,则说明之前截取的字符串要么是对象的key,要么是对象的value。或者数组的value;如果不是,则继续循环判断是否是第一个字符开始带逗号(,),如果是,则表示之前截取的字符串是对象的值或数组的某一项,判断第一个字符是否以}、]]开头,如果是,则表示是一个对象orarrayendsandstartswithotherstrings,什么都不做,继续循环1,代码实现functionjsonParser(jsonString){letsurplusStr=jsonString;//剩下的letfirstChar=surplusStr.charAt(0);letlastChar=surplusStr.charAt(surplusStr.length-1);if((firstChar!=='{'&&lastChar!=='}')&&(firstChar!=='['&&l一个字符!==']')){抛出新错误(`${jsonString}不是标准的json对象`);}让jsonObjStack=[];//json对象堆栈letkeyValuesStack=[];//存放json对象的key和value栈(二维数组),里面的value还是一个数组,里面存放的是对象,里面存放的是key和valueletresultJson=null;让dabbleQuotCount=0;//双引号的个数letcurrentStr='';//当前拦截的字符//拦截字符串letsubstr=function(needStoreStr,splitFrom,splitLength){if(needStoreStr.length>0){currentStr+=needStoreStr;}surplusStr=surplusStr.substr(splitFrom,splitLength);}//去掉字符串两端的双引号lettrimQuot=function(str){returnstr.replace(/(^"?)|("?$)/g,'');}//将值存储到栈顶console.log('push',keyValuesStackTop,value);}else{//获取栈顶的最后一项letstackTopLast=keyValuesStackTop[keyValuesStackTop.length-1];stackTopLast.value=值;console.log('pushing',stackTopLast,value);}}//处理currentStr,转换基本数据类型lethandleCurrentStr=function(str){if(!isNaN(Number(str))){str=Number(str);}elseif(str=='null'){str=null;}elseif(str=='undefined'){str=undefined;}elseif(str=='true'||str=='false'){str=str=='true';}返回海峡;}//弹出json对象栈和keyValuesStack栈的最后一位letstackPop=function(){letjsonObjStackTop=jsonObjStack.pop();让keyValuesStackTop=keyValuesStack.pop();console.log('popped',keyValuesStackTop);如果(typeofjsonObjStackTop==='undefined'||typeofkeyValuesStackTop==='undefined'){return;}if(Array.isArray(jsonObjStackTop)){keyValuesStackTop.forEach(item=>{jsonObjStackTop.push(item);});}else{keyValuesStackTop.forEach(item=>{jsonObjStackTop[item.key]=item.value;});}resultJson=jsonObjStackTop;}while(surplusStr.length>0){让firstChar=surplusStr.charAt(0);if(firstChar==='{'||firstChar==='['){//第一个字符是“{”,表示遇到了一个对象,需要在jsonObjStack中加入一个空对象,并且添加一个存储键值的空数组到keyValuesif(firstChar==='{'){console.log('第一个字符是左花括号');}else{console.log('第一个字符是左括号');}让keyValuesStackTop=keyValuesStack[keyValuesStack.length-1];让jsonObjStackTop=jsonObjStack[jsonObjStack.length-1];让obj=firstChar==='{'?{}:[];//每遇到一个对象,就需要在jsonObjStack中添加一个新的对象,并酌情在keyValuesStack栈中添加一个空数组,否则添加if(typeofjsonObjStackTop!=='undefined'){if(Array.isArray(jsonObjStackTop)){keyValuesStackTop.push(obj);}else{让lastKeyValueObj=keyValuesStackTop[keyValuesStackTop.length-1];if(typeoflastKeyValueObj.value==='undefined'){lastKeyValueObj.value=obj;}}}jsonObjStack.push(obj);keyValuesStack.push([]);surplusStr=surplusStr.substr(1);}elseif(firstChar==='"'){//判断是双引号console.log('第一个字符是双引号');//获取当前截取字符的最后一个字符letcurrentStrLast=typeofcurrentStr!=='string'?'':currentStr.charAt(currentStr.length-1);if(currentStrLast!=='\\'){//如果当前截取的字符的最后一个字符不是“\”,表示Notescapedoublequotes,即本例中不是"ab\"cd"console.log('第一个字符是双引号,不是"\\"');dabbleQuotCount++;if(dabbleQuotCount<2){console.log('第一个字符是双引号,不是一对双引号');substr(firstChar,1);}else{//如果双引号的个数为2,则可能是对象的键,或者对象的值,或者数组的值substr(firstChar,1);dabbleQuotCount=0;//获取紧跟第一个字符之后的相邻字符letnextStr=surplusStr.charAt(0);//获取栈顶存储的json对象的key值letkeyValuesStackTop=keyValuesStack[keyValuesStack.length-1];console.log('第一个字符是双引号,组成一对双引号,值为:',currentStr,keyValuesStackTop);if(nextStr===':'){//如果nextStr是冒号,则currentStr是对象的keyconsole.log('第一个字符是双引号,组成一对双引号,然后下一个字符是冒号');keyValuesStackTop.push({key:trimQuot(currentStr)});当前Str='';substr('',1);}elseif(nextStr===','||nextStr===']'||nextStr==='}'){//如果nextStr是逗号或]或},则currentStr是一个值对象或数组letjsonObjStackTop=jsonObjStack[jsonObjStack.length-1];console.log('第一个字符是双引号,组成一对双引号,下一个字符是:',nextStr,keyValuesStackTop);storeValueToStackTop(keyValuesStackTop,jsonObjStackTop,trimQuot(currentStr));如果(nextStr===','){substr('',1);}currentStr='';}}}else{console.log('第一个字符是双引号,即"\\"');substr(firstChar,1);}}elseif(firstChar==='}'||firstChar===']'){//遇到}右大括号表示对象已经结束if(firstChar==='{'){console.log('第一个字符是右花括号');}else{console.log('第一个字符是右括号');}if(currentStr){if(firstChar==='{'){联合nsole.log('第一个字符是右大括号,currentStr有值,值为:',currentStr);}else{console.log('第一个字符是右括号,currentStr有值,值为:',currentStr);}让jsonObjStackTop=jsonObjStack[jsonObjStack.length-1];让keyValuesStackTop=keyValuesStack[keyValuesStack.length-1];让tempVal=handleCurrentStr(currentStr);storeValueToStackTop(keyValuesStackTop,jsonObjStackTop,tempVal);当前Str='';}stackPop();substr('',1);}elseif(firstChar===','){//当遇到逗号时,表示之前截取的字符串是一个对象的值或者数组的某一项console.log('第一个字符是一个逗号');if(dabbleQuotCount==0){//如果双引号的个数为0,则表示逗号没有被双引号括起来,之前截取的字符串就是对象或数组项的值console.log('第一个字符是逗号,逗号不在双引号内,值为:',currentStr);如果(currentStr){让keyValuesStackTop=keyValuesStack[keyValuesStack.length-1];让jsonObjStackTop=jsonObjStack[jsonObjStack.length-1];//console.log('------------keyValuesStackTop',keyValuesStack);乐ttempVal=handleCurrentStr(currentStr);storeValueToStackTop(keyValuesStackTop,jsonObjStackTop,tempVal);}currentStr='';substr('',1);}else{console.log('第一个字符是逗号,逗号在双引号内');substr(firstChar,1);}}else{console.log('第一个字符是other');substr(firstChar,1);}}console.log('resultJson',resultJson);if(jsonObjStack.length>0||keyValuesStack.length>0){thrownewError('json解析失败!');}returnresultJson;}3.测试经过测试,可以正确解析以下字符串!letjsonStrSimple='{"name":"张三","age":23,"man":true,"cleanliness":null}';letjsonStrWithObj='{"name":"张三","age"":23,"man":true,"cleanliness":null,"score":{"Chinese":80,"mathematics":95}}';letjsonStrWithObj2='{"name":"张三","age":23,"man":true,"cleanliness":null,"subject":{"Chinese":{"teacher":"李老师","score":80},"mathematics":{"teacher":"王老师","score":95}}}';letjsonStr='{"statusCode":200,"comments":"success","data":{"adminUserId":"61973a868fef766ab4ba953b","角色ID":"61973a868fef766ab4ba953c","roleName":null,"orgId":"61973a878fef766ab4ba9686","orgName":"liyn","username":"liyn","email":null,"cellphone":null,"name":null,"nickname":"超级管理员","idcard":null,"adminType":{"code":1,"displayName":"永久账户","name":"PERMANENT"},"adminStatus":{"code":1,"displayName":"已激活","name":"AVAILABLE"},"adminStatusTime":"2021-11-1913:47:51","loginMode":null“permitLoginTime”:null,“permitLoginIp”:null,“online”:true,“updatedTime”:“2022-01-0517:41:16”,“updatedBy”:“5da7d124ce5b3053a8e9838d”,“createdTime”:“2021-11-1913:47:50","createdBy":"5da7d124ce5b3053a8e9838d","adminTypeTime":null,"defaultFlag":false,"loginFailtures":0,"authType":{"code":1,"displayName":"默认策略","name":"DEFAULT"},"sex":null,"permitLoginStart":null,"permitLoginEnd":null,"defaultPassword":false,"delFlag":false,"subject":空,“可信”:假,“companyId”:“61973a868fef766ab4ba953a”,“域”:“liyn”,“logoUrl”:“”,“shortName”:“liyn”,“emailDomain”:“”,“roleVo”:{“roleId”:“61973a868fef766ab4ba953c","roleName":"组织超级管理员","roleStatus":{"code":1,"displayName":"Enabled","name":"AVAILABLE"},"roleType":{"code":4,"displayName":"超级模块","name":"SUPER"},"roleCategory":null,"permission":null,"remark":"默认组织超级管理员","createdBy":"61973a868fef766ab4ba953b"“createdTime”:null,“updatedBy”:null,“updatedTime”:“2021-11-1913:47”,“defaultFlag”:true,“delFlag”:false,“credible”:false,“menuIds”:null}}}';letjsonStrWithArr='{"name":"张三","age":23,"man":true,"cleanliness":null,"hobby":["learning","watchingamovie","打球"]}';letjsonStrWithArr2='{"name":"张三","age":23,"man":true,"cleanliness":null,"score":{"Chinese":80,"数学":95},"爱好":["学习","看电影","打球"]}';letjsonStrWithArr3='{"name":"张三","年龄":23,"hobby":["学习",2022,"看电影",true,"打球",null,{"hobbyA":123,"arr":["说明书","分析","json",456,["嵌套数组"],undefined,true]}]}';letarrJson='["manual","parse","json"]';letarrJson1='["learning",2022,"看电影",true,"打球",null,{"hobbyA":123}]';letarrJson2='["学习",2022,"看电影",true,"打球",null,{"hobbyA":123,"arr":["手Work","parse","json",456,["嵌套数组"],undefined,true]}]';//jsonParser(jsonStrSimple);//jsonParser(jsonStrWithObj);//jsonParser(jsonStrWithObj2);jsonParser(jsonStr);//jsonParser(jsonStrWithArr);//jsonParser(jsonStrWithArr2);//jsonParser(jsonStrWithArr3);//jsonParser(arrJson);//jsonParser(arrJson1);//jsonParser(arrJson2);