一个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: '
',
 22                     r: '
',
 23                     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是两个字符
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>

运行结果

原文地址:https://www.cnblogs.com/sea-breeze/p/11747206.html