一个JSON解析器
来源
《JavaScript语言精粹(修订版)》
代码
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title></title> 7 </head> 8 9 <body> 10 <script> 11 var json_parse = function () { 12 var 13 at, 14 ch, 15 escapee = { 16 \'"\': \'"\', 17 \'\\\': \'\\\', 18 \'/\': \'/\', 19 b: \'b\', 20 f: \'\f\', 21 n: \'\n\', 22 r: \'\r\', 23 t: \'\t\' 24 }, 25 text, 26 // 抛出异常 27 error = function (m) { 28 throw { 29 name: \'SyntaxError\', 30 message: m, 31 at: at, 32 text: text 33 } 34 }, 35 // 获取下一个字符 36 next = function (c) { 37 if (c && c !== ch) { 38 error(`Expected ${c} instead of ${ch}`); 39 } 40 ch = text.charAt(at); 41 at += 1; 42 return ch; 43 }, 44 // 解析一个数字值 45 number = function () { 46 var number, string = \'\'; 47 // 负号 48 if (ch === \'-\') { 49 string = \'-\', 50 next(\'-\') 51 } 52 // 整数 53 while (ch >= \'0\' && ch <= \'9\') { 54 string += ch; 55 next(); 56 } 57 // 小数 58 if (ch === \'.\') { 59 string += \'.\'; 60 while (next() && ch >= \'0\' && ch <= \'9\') { 61 string += ch; 62 } 63 } 64 // 指数 65 if (ch === \'e\' || ch === \'E\') { 66 string += ch; 67 next(); 68 if (ch === \'-\' || ch === \'+\') { 69 string += ch; 70 next(); 71 } 72 while (ch >= \'0\' && ch <= \'9\') { 73 string += ch; 74 next(); 75 } 76 } 77 number = +string; 78 if (isNaN(number)) { 79 error(\'Bad number\') 80 } else { 81 return number; 82 } 83 }, 84 // 解析一个字符串值 85 string = function () { 86 var hex, 87 i, 88 string = \'\', 89 uffff; 90 // 字符串必须以双引号开始 91 if (ch === \'"\') { 92 while (next()) { 93 if (ch === \'"\') { 94 next(); 95 return string; 96 } else if (ch === \'\\\') { 97 next(); 98 // unicode码 99 if (ch === \'u\') { 100 uffff = 0; 101 for (i = 0; i < 4; i++) { 102 hex = parseInt(next(), 16); 103 if (!isFinite(hex)) { 104 break; 105 } 106 ufff = ufff * 16 + hex; 107 } 108 string += String.fromCharCode(ufff) 109 } 110 else if (typeof escapee[ch] === \'string\') { // 转义字符 111 string += escapee[ch] 112 } else { 113 break; 114 } 115 } else { 116 string += ch; 117 } 118 } 119 } 120 error(\'Bac string\'); 121 }, 122 // 跳过空白 123 white = function () { 124 while (ch && ch <= \' \') { 125 next(); 126 } 127 }, 128 // 解析 true、false、null 129 word = function () { 130 switch (ch) { 131 case \'t\': 132 next(\'t\'); 133 next(\'r\'); 134 next(\'u\'); 135 next(\'e\'); 136 return true; 137 case \'f\': 138 next(\'f\'); 139 next(\'a\'); 140 next(\'l\'); 141 next(\'s\'); 142 next(\'e\'); 143 return true; 144 case \'n\': 145 next(\'n\'); 146 next(\'u\'); 147 next(\'l\'); 148 next(\'l\'); 149 return true; 150 } 151 error(`Unexpected ${ch}`) 152 }, 153 // 解析一个数组值 154 array = function () { 155 var array = []; 156 if (ch === \'[\') { 157 next(\'[\'); 158 white(); 159 if (ch === \']\') { 160 next(\']\'); 161 return array; 162 } 163 while (ch) { 164 array.push(value()); 165 white(); 166 if (ch === \']\') { 167 next(\']\'); 168 return array; 169 } 170 next(\',\'); 171 white(); 172 } 173 } 174 error(\'Bad array\'); 175 }, 176 // 解析一个对象值 177 object = function () { 178 var key, object = {}; 179 if (ch === \'{\') { 180 next(\'{\'); 181 white(); 182 if (ch === \'}\') { 183 next(\'}\'); 184 return object; 185 } 186 while (ch) { 187 key = string(); 188 white(); 189 next(\':\'); 190 object[key] = value(); 191 white(); 192 if (ch === \'}\') { 193 next(\'}\'); 194 return object; 195 } 196 next(\',\'); 197 white(); 198 } 199 } 200 error(\'Bad object\'); 201 }, 202 // 解析一个JSON值。它可以是对象、数组、字符串、数字、一个词。 203 value = function () { 204 white(); 205 switch (ch) { 206 case \'{\': 207 return object(); 208 case \'[\': 209 return array(); 210 case \'"\': 211 return string(); 212 case \'-\': 213 return number; 214 default: 215 return ch >= \'0\' && ch <= \'9\' ? number() : word(); 216 } 217 }; 218 // 返回json_parse函数 219 return function (source, reviver) { 220 var result; 221 text = source; 222 at = 0; 223 ch = \' \'; 224 result = value(); 225 white(); 226 if (ch) { // 多余的非空白字符 227 error(\'Syntax error\'); 228 } 229 return typeof reviver === \'function\' ? function walk(holder, key) { 230 var k, v, value = holder[key]; 231 if (value && typeof value === \'object\') { 232 // 递归处理对象的属性 233 for (k in value) { 234 if (Object.hasOwnProperty.call(value, k)) { 235 v = walk(value, k); 236 if (v !== undefined) { 237 value[k] = v; 238 } else { 239 delete value[k] 240 } 241 } 242 } 243 } 244 // 处理对象 245 return reviver.call(holder, key, value); 246 }({ \'\': result }, \'\') : result; 247 } 248 }(); 249 // \n是一个字符,\\n是两个字符 250 const str = \'{"name":"饮料","price":2.5,"cool":true,"description":["雪碧","可乐"],"escapseSlash":"\\/","escapeN":"\\n"}\'; 251 console.log(json_parse(str, (key, val) => val)) 252 </script> 253 </body> 254 255 </html>
运行结果