【前端三分钟】写一个JSON.Parse解析器

在这里插入图片描述

//使用递归降序法
let JsonParse = function() {
		let at, //当前字符索引
			ch, //当前字符
			escapee = {
				'"': '"',
				'\\': '\\',
				'/': '/',
				b: 'b',
				f: '\f',
				n: '\n',
				r: '\r',
				t: '\t'
			},
			text,
			error = function (m) {
			//错误处理
				throw {
					name: 'SyntaxError',
					message: m,
					at: at,
					text: text
				};
			},
			next = function (c) {
				//检验c是否匹配当前字符
				if(c && c !== ch) {
					error("Expected '"+c+"' instead of'"+ ch+"'");
				}
				//获取下一个字符,当没有下一个字符时,返回空字符串
				ch = text.charAt(at);
				at +=1;
				return ch;
			},
			number = function() {
				//解析一个数字值
				let number,
					string = '';
				if(ch === '-') {
					string = '-';
					next('-');
				}
				while (ch >= '0' && ch <= '9') {
					string += ch;
					next();
				}
				if (ch === '.' ) {
					string += '.';
				}
				while (next() && ch >= '0' && ch <= '9') {
					string += ch;
				}
			
				if(ch === 'e' || ch === 'E') {
					string += ch;
					next();
					if (ch === '-' || ch === '+') {
						string += ch;
						next();
					}
					while (ch >= '0' && ch <= '9') {
						string += ch;
						next();
					}
				}
				number =+ string;
				if (isNaN(number)) {
					error("Bad number");
				}else {
					return number;
				}

			},
			string = function () {
				//解析一个字符串
				var hex,
					i,
					string = '',
					uffff;
				//当解析字符串值时,必须找到"和\字符
				if (ch==='"') {
					while (next()) {
						if (ch === '"') {
							next();
							return string;
						}else if (ch === '\\') {
							next();
							if (ch === 'u') {
								uffff = 0;
								for (i = 0; i < 4;i +=1) {
									hex = parseInt(next(), 16);
									if (!isFinite(hex)) {
										break;
									}
									uffff = uffff * 16 +hex;
								}
								string += String.fromCharCode(uffff);
							}else if (typeof escapee[ch] === 'string') {
								string += escapee[ch];
							}else {
								break;
							}
						}else {
								string += ch;
						}
					}
				}
				error("Bad string");
			},
			white = function() {
				//跳过空白
				while (ch && ch <= ' ') {
					next();
				}
			},
			word = function() {
				//true,false或null
				switch (ch) {
					case 't':
						next('t');
						next('r');
						next('u');
						next('e');
						return true;
					case 'f':
						next('f');
						next('a');
						next('l');
						next('s');
						next('e');
						return false;
					case 'n':
						next('n');
						next('u');
						next('l');
						next('l');
						return null;
				}
				error("Unexpected'"+ch+"'");
			},
			array = function () {
				//解析一个数组值
				let array = [];
				if (ch === '[') {
					next('[');
					white();
				}
				if (ch === ']') {
					next(']');
					return array;//空数组
				}
				while (ch) {
					array.push(value());
					white();
					if (ch === ']') {
						next(']');
						return array;
					}
					next(',');
					white();
				}
				error("Bad array");
			},
			object = function () {
				//解析一个对象值
				let key,
					object = [];
				if (ch === '{') {
					next('{');
					white();
					if (ch === '}') {
						next('}');
						return object; //空对象
					}
					while (ch) {
						key = string();
						white();
						next(':');
						object[key] = value();
						white();
						if (ch === '}') {
							next('}');
							return object;
						}
						next(',');
						white();
					}
				}
				error("Bad object");
			},
			value = function () {
				//解析一个JSON值,它可以是对象、数组、字符串、数字或词
				white();
				switch (ch) {
					case '{':
						return object();
					case '[':
						return array();
					case '"':
						return string();
					case '-':
						return number();
					default:
						return ch >= '0' && ch<='9' ? number() : word();
				}
			};
			//返回JsonParse函数
			return function (source,reviver) {
				let result;
				text= source;
				at = 0;
				ch = ' ';
				result = value();
				white();
				if (ch) {
					error("Syntax error");
				}
				//如果存在reviver函数,则递归对这个新结构调用walk函数
				//开始时先创建一个临时启动对象,并以一个空字符串作为键名保存结果
				//如果没有reviver函数,就简单返回结果。
				return typeof reviver === 'function' ? 
					function walk(holder, key) {
						var k,v,val = holder[key];
						if(val && typeof val === 'object') {
							for(k in val) {
								if(Object.hasOwnProperty.call(val,k)) {
									v = walk(val,k);
									if(v !== undefined) {
										val[k] = v;
									}else {
										delete val[k];
									}
								}
							}
						}
						return reviver.call(holder,key,val);
					}({'': result},'') : result;
			}
	}();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程轨迹_

期望和你分享一杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值