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

2023-10-07 18:45:44 浏览数 (1)

代码语言:javascript复制
//使用递归降序法
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 人点赞