码迷,mamicode.com
首页 > 编程语言 > 详细

<JavaScript语言精粹>JSON解析器源码阅读

时间:2018-05-12 21:37:08      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:white   har   sage   []   from   als   console   expected   cal   

  1 // 这是一个用JavaScript编写JSON解析器的实现方案:
  2 var jsonParser = (function() {
  3   // 这是一个能把JSON文本解析成JavaScript数据结构的函数。
  4   // 它是一个简单的递归降序解析器。
  5   // 我们在另一个函数中定义此函数,以避免创建全局变量。
  6 
  7   var at, // 当前字符索引
  8     ch, // 当前字符
  9     escapee = {
 10       ‘"‘: ‘"‘,
 11       "\\": "\\",
 12       "/": "/",
 13       b: "b",
 14       f: "\f",
 15       n: "\n",
 16       r: "\r",
 17       t: "\t"
 18     },
 19     text,
 20     error = function(m) {
 21       // 当某处出错时,调用error。
 22       throw {
 23         name: "SyntaxError",
 24         messsage: m,
 25         at: at,
 26         text: text
 27       };
 28     },
 29     next = function(c) {
 30       // 如果提供了参数 c, 那么检查它是否匹配当前字符。
 31       if (c && c !== ch) {
 32         error("Expected ‘" + c + "‘ insttead of ‘" + ch + "‘");
 33       }
 34 
 35       // 获取下一个字符。当没有下一个字符时,返回一个空字符串。
 36       ch = text.charAt(at);
 37       at += 1;
 38       return ch;
 39     },
 40     number = function() {
 41       // 解析一个数字值。
 42       var number,
 43         string = "";
 44       if (ch === "-") {
 45         string = "-";
 46         next("-");
 47       }
 48       while (ch >= "0" && ch <= "9") {
 49         string += ch;
 50         next();
 51       }
 52       if (ch === ".") {
 53         string += ".";
 54         while (next() && ch >= "0" && ch <= "9") {
 55           string += ch;
 56         }
 57       }
 58       if (ch == "e" || ch == "E") {
 59         string += ch;
 60         next();
 61         if (ch === "-" || ch === "+") {
 62           string += ch;
 63           next();
 64         }
 65         while (ch >= "0" && ch <= "9") {
 66           string += ch;
 67           next();
 68         }
 69       }
 70       // reeser: 加一个字符串, 是一种技巧, 用于将字符串转换为数字
 71       number = +string;
 72       if (isNaN(number)) {
 73         error("Bad number");
 74       } else {
 75         return number;
 76       }
 77     },
 78     string = function() {
 79       // 解析一个字符串值。
 80       var hex,
 81         i,
 82         string = "",
 83         uffff;
 84       // 当解析字符串值时,我们必须找到 " 和 \ 字符。
 85       if (ch === ‘"‘) {
 86         while (next()) {
 87           if (ch === ‘"‘) {
 88             next();
 89             return string;
 90           } else if (ch === "\\") {
 91             next();
 92             if (ch === "u") {
 93               uffff = 0;
 94               for (i = 0; i < 4; i += 1) {
 95                 hex = parseInt(next(), 16);
 96                 if (!isFinite(hex)) {
 97                   break;
 98                 }
 99                 uffff = uffff * 16 + hex;
100               }
101               string += String.fromCharCode(uffff);
102             } else if (typeof escapee[ch] === "string") {
103               string += escapee[ch];
104             } else {
105               break;
106             }
107           } else {
108             string += ch;
109           }
110         }
111       }
112       error("Bad string");
113     },
114     white = function() {
115       // 跳过空白
116       // reeser: ascii表中, 小于等于32(空白字符)的,都属于空白字符
117       while (ch && ch <= " ") {
118         next();
119       }
120     },
121     word = function() {
122       // true, false 或者 null
123       switch (ch) {
124         case "t":
125           next("t");
126           next("r");
127           next("u");
128           next("e");
129           return true;
130         case "f":
131           next("f");
132           next("a");
133           next("l");
134           next("s");
135           next("e");
136           return false;
137         case "n":
138           next("n");
139           next("u");
140           next("l");
141           next("l");
142           return null;
143       }
144       error("Unexpected ‘" + ch + "‘");
145     },
146     value, // 值函数的占位符。
147     array = function() {
148       // 解析一个数组值。
149       var array = [];
150       if (ch === "[") {
151         next(‘[‘);
152         white();
153         if (ch === "]") {
154           next("]");
155           return array; // 空数组
156         }
157         while (ch) {
158           array.push(value());
159           white();
160           if (ch === "]") {
161             next("]");
162             return array;
163           }
164           next(",");
165           white();
166         }
167       }
168       error("Bad array");
169     },
170     object = function() {
171       // 解析一个对象值
172       var key,
173         object = {};
174       if (ch === "{") {
175         next("{");
176         white();
177         if (ch === "}") {
178           next("}");
179           return object; // 空对象
180         }
181         while (ch) {
182           key = string();
183           white();
184           next(":");
185           object[key] = value();
186           white();
187           if (ch === "}") {
188             next("}");
189             return object;
190           }
191           next(",");
192           white();
193         }
194       }
195       error("Bad object");
196     };
197   value = function() {
198     // 解析一个JSON值。它可以是对象、数组、字符串、数字或一个词。
199     white();
200     switch (ch) {
201       case "{":
202         return object();
203       case "[":
204         return array();
205       case ‘"‘:
206         return string();
207       case "-":
208         return number();
209       default:
210         return ch >= "0" && ch <= "9" ? number() : word();
211     }
212   };
213   // 返回json_parse 函数。它能访问上述所有的函数和变量。
214   return function(source, reviver) {
215     var result;
216     text = source;
217     at = 0;
218     ch = " ";
219     result = value();
220     white();
221     if (ch) {
222       error("Syntax error");
223     }
224 
225     // 如果存在reviver 函数,我们就递归地对这个新结构调用walk函数,
226     // 开始时先创建一个临时的启动对象,并以一个空字符串作为键名保存结果,
227     // 然后传递每个键值对给reviver函数去处理可能存在的转换。
228     // 如果没有reviver函数,我们就简单地返回这个结果。
229     return typeof reviver === "function"
230       ? (function walk(holder, key) {
231           var k,
232             v,
233             value = holder[key];
234           // reeser: 数组也是object类型;也可以通过for in 遍历;
235           if (value && typeof value === "object") {
236             for (k in value) {
237               if (Object.hasOwnProperty.call(value, k)) {
238                 v = walk(value, k);
239                 if (v !== undefined) {
240                   value[k] = v;
241                 } else {
242                   delete value[k];
243                 }
244               }
245             }
246           }
247           return reviver.call(holder, key, value);
248         })({ "": result }, "")
249       : result;
250   };
251 })();
252 
253 
254 console.log(JSON.stringify(jsonParser(‘[{"a" :1}]‘, (key, value)=>{
255   if (key == ‘a‘)
256   {
257     console.log(`found key a. value:${value}`);
258   }
259   return value;
260 })));

 

<JavaScript语言精粹>JSON解析器源码阅读

标签:white   har   sage   []   from   als   console   expected   cal   

原文地址:https://www.cnblogs.com/reeser/p/9029947.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!