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