前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【前端三分钟】写一个JSON.Parse解析器

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

作者头像
前端修罗场
发布2023-10-07 18:45:44
1820
发布2023-10-07 18:45:44
举报
文章被收录于专栏:Web 技术
代码语言: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;
			}
	}();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档