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 })));