Mercurial > wikked
comparison static/js/jsonjs/json_parse.js @ 60:8250c977bc50
Moved static files to the root directory.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 05 Feb 2013 14:49:34 -0800 |
parents | wikked/static/js/jsonjs/json_parse.js@c946f4facfa2 |
children |
comparison
equal
deleted
inserted
replaced
59:59ecc742ab8e | 60:8250c977bc50 |
---|---|
1 /* | |
2 json_parse.js | |
3 2012-06-20 | |
4 | |
5 Public Domain. | |
6 | |
7 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |
8 | |
9 This file creates a json_parse function. | |
10 | |
11 json_parse(text, reviver) | |
12 This method parses a JSON text to produce an object or array. | |
13 It can throw a SyntaxError exception. | |
14 | |
15 The optional reviver parameter is a function that can filter and | |
16 transform the results. It receives each of the keys and values, | |
17 and its return value is used instead of the original value. | |
18 If it returns what it received, then the structure is not modified. | |
19 If it returns undefined then the member is deleted. | |
20 | |
21 Example: | |
22 | |
23 // Parse the text. Values that look like ISO date strings will | |
24 // be converted to Date objects. | |
25 | |
26 myData = json_parse(text, function (key, value) { | |
27 var a; | |
28 if (typeof value === 'string') { | |
29 a = | |
30 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); | |
31 if (a) { | |
32 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], | |
33 +a[5], +a[6])); | |
34 } | |
35 } | |
36 return value; | |
37 }); | |
38 | |
39 This is a reference implementation. You are free to copy, modify, or | |
40 redistribute. | |
41 | |
42 This code should be minified before deployment. | |
43 See http://javascript.crockford.com/jsmin.html | |
44 | |
45 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO | |
46 NOT CONTROL. | |
47 */ | |
48 | |
49 /*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, | |
50 hasOwnProperty, message, n, name, prototype, push, r, t, text | |
51 */ | |
52 | |
53 var json_parse = (function () { | |
54 "use strict"; | |
55 | |
56 // This is a function that can parse a JSON text, producing a JavaScript | |
57 // data structure. It is a simple, recursive descent parser. It does not use | |
58 // eval or regular expressions, so it can be used as a model for implementing | |
59 // a JSON parser in other languages. | |
60 | |
61 // We are defining the function inside of another function to avoid creating | |
62 // global variables. | |
63 | |
64 var at, // The index of the current character | |
65 ch, // The current character | |
66 escapee = { | |
67 '"': '"', | |
68 '\\': '\\', | |
69 '/': '/', | |
70 b: '\b', | |
71 f: '\f', | |
72 n: '\n', | |
73 r: '\r', | |
74 t: '\t' | |
75 }, | |
76 text, | |
77 | |
78 error = function (m) { | |
79 | |
80 // Call error when something is wrong. | |
81 | |
82 throw { | |
83 name: 'SyntaxError', | |
84 message: m, | |
85 at: at, | |
86 text: text | |
87 }; | |
88 }, | |
89 | |
90 next = function (c) { | |
91 | |
92 // If a c parameter is provided, verify that it matches the current character. | |
93 | |
94 if (c && c !== ch) { | |
95 error("Expected '" + c + "' instead of '" + ch + "'"); | |
96 } | |
97 | |
98 // Get the next character. When there are no more characters, | |
99 // return the empty string. | |
100 | |
101 ch = text.charAt(at); | |
102 at += 1; | |
103 return ch; | |
104 }, | |
105 | |
106 number = function () { | |
107 | |
108 // Parse a number value. | |
109 | |
110 var number, | |
111 string = ''; | |
112 | |
113 if (ch === '-') { | |
114 string = '-'; | |
115 next('-'); | |
116 } | |
117 while (ch >= '0' && ch <= '9') { | |
118 string += ch; | |
119 next(); | |
120 } | |
121 if (ch === '.') { | |
122 string += '.'; | |
123 while (next() && ch >= '0' && ch <= '9') { | |
124 string += ch; | |
125 } | |
126 } | |
127 if (ch === 'e' || ch === 'E') { | |
128 string += ch; | |
129 next(); | |
130 if (ch === '-' || ch === '+') { | |
131 string += ch; | |
132 next(); | |
133 } | |
134 while (ch >= '0' && ch <= '9') { | |
135 string += ch; | |
136 next(); | |
137 } | |
138 } | |
139 number = +string; | |
140 if (!isFinite(number)) { | |
141 error("Bad number"); | |
142 } else { | |
143 return number; | |
144 } | |
145 }, | |
146 | |
147 string = function () { | |
148 | |
149 // Parse a string value. | |
150 | |
151 var hex, | |
152 i, | |
153 string = '', | |
154 uffff; | |
155 | |
156 // When parsing for string values, we must look for " and \ characters. | |
157 | |
158 if (ch === '"') { | |
159 while (next()) { | |
160 if (ch === '"') { | |
161 next(); | |
162 return string; | |
163 } | |
164 if (ch === '\\') { | |
165 next(); | |
166 if (ch === 'u') { | |
167 uffff = 0; | |
168 for (i = 0; i < 4; i += 1) { | |
169 hex = parseInt(next(), 16); | |
170 if (!isFinite(hex)) { | |
171 break; | |
172 } | |
173 uffff = uffff * 16 + hex; | |
174 } | |
175 string += String.fromCharCode(uffff); | |
176 } else if (typeof escapee[ch] === 'string') { | |
177 string += escapee[ch]; | |
178 } else { | |
179 break; | |
180 } | |
181 } else { | |
182 string += ch; | |
183 } | |
184 } | |
185 } | |
186 error("Bad string"); | |
187 }, | |
188 | |
189 white = function () { | |
190 | |
191 // Skip whitespace. | |
192 | |
193 while (ch && ch <= ' ') { | |
194 next(); | |
195 } | |
196 }, | |
197 | |
198 word = function () { | |
199 | |
200 // true, false, or null. | |
201 | |
202 switch (ch) { | |
203 case 't': | |
204 next('t'); | |
205 next('r'); | |
206 next('u'); | |
207 next('e'); | |
208 return true; | |
209 case 'f': | |
210 next('f'); | |
211 next('a'); | |
212 next('l'); | |
213 next('s'); | |
214 next('e'); | |
215 return false; | |
216 case 'n': | |
217 next('n'); | |
218 next('u'); | |
219 next('l'); | |
220 next('l'); | |
221 return null; | |
222 } | |
223 error("Unexpected '" + ch + "'"); | |
224 }, | |
225 | |
226 value, // Place holder for the value function. | |
227 | |
228 array = function () { | |
229 | |
230 // Parse an array value. | |
231 | |
232 var array = []; | |
233 | |
234 if (ch === '[') { | |
235 next('['); | |
236 white(); | |
237 if (ch === ']') { | |
238 next(']'); | |
239 return array; // empty array | |
240 } | |
241 while (ch) { | |
242 array.push(value()); | |
243 white(); | |
244 if (ch === ']') { | |
245 next(']'); | |
246 return array; | |
247 } | |
248 next(','); | |
249 white(); | |
250 } | |
251 } | |
252 error("Bad array"); | |
253 }, | |
254 | |
255 object = function () { | |
256 | |
257 // Parse an object value. | |
258 | |
259 var key, | |
260 object = {}; | |
261 | |
262 if (ch === '{') { | |
263 next('{'); | |
264 white(); | |
265 if (ch === '}') { | |
266 next('}'); | |
267 return object; // empty object | |
268 } | |
269 while (ch) { | |
270 key = string(); | |
271 white(); | |
272 next(':'); | |
273 if (Object.hasOwnProperty.call(object, key)) { | |
274 error('Duplicate key "' + key + '"'); | |
275 } | |
276 object[key] = value(); | |
277 white(); | |
278 if (ch === '}') { | |
279 next('}'); | |
280 return object; | |
281 } | |
282 next(','); | |
283 white(); | |
284 } | |
285 } | |
286 error("Bad object"); | |
287 }; | |
288 | |
289 value = function () { | |
290 | |
291 // Parse a JSON value. It could be an object, an array, a string, a number, | |
292 // or a word. | |
293 | |
294 white(); | |
295 switch (ch) { | |
296 case '{': | |
297 return object(); | |
298 case '[': | |
299 return array(); | |
300 case '"': | |
301 return string(); | |
302 case '-': | |
303 return number(); | |
304 default: | |
305 return ch >= '0' && ch <= '9' ? number() : word(); | |
306 } | |
307 }; | |
308 | |
309 // Return the json_parse function. It will have access to all of the above | |
310 // functions and variables. | |
311 | |
312 return function (source, reviver) { | |
313 var result; | |
314 | |
315 text = source; | |
316 at = 0; | |
317 ch = ' '; | |
318 result = value(); | |
319 white(); | |
320 if (ch) { | |
321 error("Syntax error"); | |
322 } | |
323 | |
324 // If there is a reviver function, we recursively walk the new structure, | |
325 // passing each name/value pair to the reviver function for possible | |
326 // transformation, starting with a temporary root object that holds the result | |
327 // in an empty key. If there is not a reviver function, we simply return the | |
328 // result. | |
329 | |
330 return typeof reviver === 'function' | |
331 ? (function walk(holder, key) { | |
332 var k, v, value = holder[key]; | |
333 if (value && typeof value === 'object') { | |
334 for (k in value) { | |
335 if (Object.prototype.hasOwnProperty.call(value, k)) { | |
336 v = walk(value, k); | |
337 if (v !== undefined) { | |
338 value[k] = v; | |
339 } else { | |
340 delete value[k]; | |
341 } | |
342 } | |
343 } | |
344 } | |
345 return reviver.call(holder, key, value); | |
346 }({'': result}, '')) | |
347 : result; | |
348 }; | |
349 }()); |