(file) Return to json2.js CVS log (file) (dir) Up to [Pegasus] / pegasus / www / js

  1 lawrence.luo 1.2 /*
  2                      json2.js
  3                      2013-05-26
  4                  
  5                      Public Domain.
  6                  
  7                      NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  8                  
  9                      See http://www.JSON.org/js.html
 10                  
 11                  
 12                      This code should be minified before deployment.
 13                      See http://javascript.crockford.com/jsmin.html
 14                  
 15                      USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
 16                      NOT CONTROL.
 17                  
 18                  
 19                      This file creates a global JSON object containing two methods: stringify
 20                      and parse.
 21                  
 22 lawrence.luo 1.2         JSON.stringify(value, replacer, space)
 23                              value       any JavaScript value, usually an object or array.
 24                  
 25                              replacer    an optional parameter that determines how object
 26                                          values are stringified for objects. It can be a
 27                                          function or an array of strings.
 28                  
 29                              space       an optional parameter that specifies the indentation
 30                                          of nested structures. If it is omitted, the text will
 31                                          be packed without extra whitespace. If it is a number,
 32                                          it will specify the number of spaces to indent at each
 33                                          level. If it is a string (such as '\t' or ' '),
 34                                          it contains the characters used to indent at each level.
 35                  
 36                              This method produces a JSON text from a JavaScript value.
 37                  
 38                              When an object value is found, if the object contains a toJSON
 39                              method, its toJSON method will be called and the result will be
 40                              stringified. A toJSON method does not serialize: it returns the
 41                              value represented by the name/value pair that should be serialized,
 42                              or undefined if nothing should be serialized. The toJSON method
 43 lawrence.luo 1.2             will be passed the key associated with the value, and this will be
 44                              bound to the value
 45                  
 46                              For example, this would serialize Dates as ISO strings.
 47                  
 48                                  Date.prototype.toJSON = function (key) {
 49                                      function f(n) {
 50                                          // Format integers to have at least two digits.
 51                                          return n < 10 ? '0' + n : n;
 52                                      }
 53                  
 54                                      return this.getUTCFullYear()   + '-' +
 55                                           f(this.getUTCMonth() + 1) + '-' +
 56                                           f(this.getUTCDate())      + 'T' +
 57                                           f(this.getUTCHours())     + ':' +
 58                                           f(this.getUTCMinutes())   + ':' +
 59                                           f(this.getUTCSeconds())   + 'Z';
 60                                  };
 61                  
 62                              You can provide an optional replacer method. It will be passed the
 63                              key and value of each member, with this bound to the containing
 64 lawrence.luo 1.2             object. The value that is returned from your method will be
 65                              serialized. If your method returns undefined, then the member will
 66                              be excluded from the serialization.
 67                  
 68                              If the replacer parameter is an array of strings, then it will be
 69                              used to select the members to be serialized. It filters the results
 70                              such that only members with keys listed in the replacer array are
 71                              stringified.
 72                  
 73                              Values that do not have JSON representations, such as undefined or
 74                              functions, will not be serialized. Such values in objects will be
 75                              dropped; in arrays they will be replaced with null. You can use
 76                              a replacer function to replace those with JSON values.
 77                              JSON.stringify(undefined) returns undefined.
 78                  
 79                              The optional space parameter produces a stringification of the
 80                              value that is filled with line breaks and indentation to make it
 81                              easier to read.
 82                  
 83                              If the space parameter is a non-empty string, then that string will
 84                              be used for indentation. If the space parameter is a number, then
 85 lawrence.luo 1.2             the indentation will be that many spaces.
 86                  
 87                              Example:
 88                  
 89                              text = JSON.stringify(['e', {pluribus: 'unum'}]);
 90                              // text is '["e",{"pluribus":"unum"}]'
 91                  
 92                  
 93                              text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
 94                              // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
 95                  
 96                              text = JSON.stringify([new Date()], function (key, value) {
 97                                  return this[key] instanceof Date ?
 98                                      'Date(' + this[key] + ')' : value;
 99                              });
100                              // text is '["Date(---current time---)"]'
101                  
102                  
103                          JSON.parse(text, reviver)
104                              This method parses a JSON text to produce an object or array.
105                              It can throw a SyntaxError exception.
106 lawrence.luo 1.2 
107                              The optional reviver parameter is a function that can filter and
108                              transform the results. It receives each of the keys and values,
109                              and its return value is used instead of the original value.
110                              If it returns what it received, then the structure is not modified.
111                              If it returns undefined then the member is deleted.
112                  
113                              Example:
114                  
115                              // Parse the text. Values that look like ISO date strings will
116                              // be converted to Date objects.
117                  
118                              myData = JSON.parse(text, function (key, value) {
119                                  var a;
120                                  if (typeof value === 'string') {
121                                      a =
122                  /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
123                                      if (a) {
124                                          return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
125                                              +a[5], +a[6]));
126                                      }
127 lawrence.luo 1.2                 }
128                                  return value;
129                              });
130                  
131                              myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
132                                  var d;
133                                  if (typeof value === 'string' &&
134                                          value.slice(0, 5) === 'Date(' &&
135                                          value.slice(-1) === ')') {
136                                      d = new Date(value.slice(5, -1));
137                                      if (d) {
138                                          return d;
139                                      }
140                                  }
141                                  return value;
142                              });
143                  
144                  
145                      This is a reference implementation. You are free to copy, modify, or
146                      redistribute.
147                  */
148 lawrence.luo 1.2 
149                  /*jslint evil: true, regexp: true */
150                  
151                  /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
152                      call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
153                      getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
154                      lastIndex, length, parse, prototype, push, replace, slice, stringify,
155                      test, toJSON, toString, valueOf
156                  */
157                  
158                  
159                  // Create a JSON object only if one does not already exist. We create the
160                  // methods in a closure to avoid creating global variables.
161                  
162                  if (typeof JSON !== 'object') {
163                      JSON = {};
164                  }
165                  
166                  (function () {
167                      'use strict';
168                  
169 lawrence.luo 1.2     function f(n) {
170                          // Format integers to have at least two digits.
171                          return n < 10 ? '0' + n : n;
172                      }
173                  
174                      if (typeof Date.prototype.toJSON !== 'function') {
175                  
176                          Date.prototype.toJSON = function () {
177                  
178                              return isFinite(this.valueOf())
179                                  ? this.getUTCFullYear()     + '-' +
180                                      f(this.getUTCMonth() + 1) + '-' +
181                                      f(this.getUTCDate())      + 'T' +
182                                      f(this.getUTCHours())     + ':' +
183                                      f(this.getUTCMinutes())   + ':' +
184                                      f(this.getUTCSeconds())   + 'Z'
185                                  : null;
186                          };
187                  
188                          String.prototype.toJSON      =
189                              Number.prototype.toJSON  =
190 lawrence.luo 1.2             Boolean.prototype.toJSON = function () {
191                                  return this.valueOf();
192                              };
193                      }
194                  
195                      var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
196                          escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
197                          gap,
198                          indent,
199                          meta = {    // table of character substitutions
200                              '\b': '\\b',
201                              '\t': '\\t',
202                              '\n': '\\n',
203                              '\f': '\\f',
204                              '\r': '\\r',
205                              '"' : '\\"',
206                              '\\': '\\\\'
207                          },
208                          rep;
209                  
210                  
211 lawrence.luo 1.2     function quote(string) {
212                  
213                  // If the string contains no control characters, no quote characters, and no
214                  // backslash characters, then we can safely slap some quotes around it.
215                  // Otherwise we must also replace the offending characters with safe escape
216                  // sequences.
217                  
218                          escapable.lastIndex = 0;
219                          return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
220                              var c = meta[a];
221                              return typeof c === 'string'
222                                  ? c
223                                  : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
224                          }) + '"' : '"' + string + '"';
225                      }
226                  
227                  
228                      function str(key, holder) {
229                  
230                  // Produce a string from holder[key].
231                  
232 lawrence.luo 1.2         var i,          // The loop counter.
233                              k,          // The member key.
234                              v,          // The member value.
235                              length,
236                              mind = gap,
237                              partial,
238                              value = holder[key];
239                  
240                  // If the value has a toJSON method, call it to obtain a replacement value.
241                  
242                          if (value && typeof value === 'object' &&
243                                  typeof value.toJSON === 'function') {
244                              value = value.toJSON(key);
245                          }
246                  
247                  // If we were called with a replacer function, then call the replacer to
248                  // obtain a replacement value.
249                  
250                          if (typeof rep === 'function') {
251                              value = rep.call(holder, key, value);
252                          }
253 lawrence.luo 1.2 
254                  // What happens next depends on the value's type.
255                  
256                          switch (typeof value) {
257                          case 'string':
258                              return quote(value);
259                  
260                          case 'number':
261                  
262                  // JSON numbers must be finite. Encode non-finite numbers as null.
263                  
264                              return isFinite(value) ? String(value) : 'null';
265                  
266                          case 'boolean':
267                          case 'null':
268                  
269                  // If the value is a boolean or null, convert it to a string. Note:
270                  // typeof null does not produce 'null'. The case is included here in
271                  // the remote chance that this gets fixed someday.
272                  
273                              return String(value);
274 lawrence.luo 1.2 
275                  // If the type is 'object', we might be dealing with an object or an array or
276                  // null.
277                  
278                          case 'object':
279                  
280                  // Due to a specification blunder in ECMAScript, typeof null is 'object',
281                  // so watch out for that case.
282                  
283                              if (!value) {
284                                  return 'null';
285                              }
286                  
287                  // Make an array to hold the partial results of stringifying this object value.
288                  
289                              gap += indent;
290                              partial = [];
291                  
292                  // Is the value an array?
293                  
294                              if (Object.prototype.toString.apply(value) === '[object Array]') {
295 lawrence.luo 1.2 
296                  // The value is an array. Stringify every element. Use null as a placeholder
297                  // for non-JSON values.
298                  
299                                  length = value.length;
300                                  for (i = 0; i < length; i += 1) {
301                                      partial[i] = str(i, value) || 'null';
302                                  }
303                  
304                  // Join all of the elements together, separated with commas, and wrap them in
305                  // brackets.
306                  
307                                  v = partial.length === 0
308                                      ? '[]'
309                                      : gap
310                                      ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
311                                      : '[' + partial.join(',') + ']';
312                                  gap = mind;
313                                  return v;
314                              }
315                  
316 lawrence.luo 1.2 // If the replacer is an array, use it to select the members to be stringified.
317                  
318                              if (rep && typeof rep === 'object') {
319                                  length = rep.length;
320                                  for (i = 0; i < length; i += 1) {
321                                      if (typeof rep[i] === 'string') {
322                                          k = rep[i];
323                                          v = str(k, value);
324                                          if (v) {
325                                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
326                                          }
327                                      }
328                                  }
329                              } else {
330                  
331                  // Otherwise, iterate through all of the keys in the object.
332                  
333                                  for (k in value) {
334                                      if (Object.prototype.hasOwnProperty.call(value, k)) {
335                                          v = str(k, value);
336                                          if (v) {
337 lawrence.luo 1.2                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
338                                          }
339                                      }
340                                  }
341                              }
342                  
343                  // Join all of the member texts together, separated with commas,
344                  // and wrap them in braces.
345                  
346                              v = partial.length === 0
347                                  ? '{}'
348                                  : gap
349                                  ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
350                                  : '{' + partial.join(',') + '}';
351                              gap = mind;
352                              return v;
353                          }
354                      }
355                  
356                  // If the JSON object does not yet have a stringify method, give it one.
357                  
358 lawrence.luo 1.2     if (typeof JSON.stringify !== 'function') {
359                          JSON.stringify = function (value, replacer, space) {
360                  
361                  // The stringify method takes a value and an optional replacer, and an optional
362                  // space parameter, and returns a JSON text. The replacer can be a function
363                  // that can replace values, or an array of strings that will select the keys.
364                  // A default replacer method can be provided. Use of the space parameter can
365                  // produce text that is more easily readable.
366                  
367                              var i;
368                              gap = '';
369                              indent = '';
370                  
371                  // If the space parameter is a number, make an indent string containing that
372                  // many spaces.
373                  
374                              if (typeof space === 'number') {
375                                  for (i = 0; i < space; i += 1) {
376                                      indent += ' ';
377                                  }
378                  
379 lawrence.luo 1.2 // If the space parameter is a string, it will be used as the indent string.
380                  
381                              } else if (typeof space === 'string') {
382                                  indent = space;
383                              }
384                  
385                  // If there is a replacer, it must be a function or an array.
386                  // Otherwise, throw an error.
387                  
388                              rep = replacer;
389                              if (replacer && typeof replacer !== 'function' &&
390                                      (typeof replacer !== 'object' ||
391                                      typeof replacer.length !== 'number')) {
392                                  throw new Error('JSON.stringify');
393                              }
394                  
395                  // Make a fake root object containing our value under the key of ''.
396                  // Return the result of stringifying the value.
397                  
398                              return str('', {'': value});
399                          };
400 lawrence.luo 1.2     }
401                  
402                  
403                  // If the JSON object does not yet have a parse method, give it one.
404                  
405                      if (typeof JSON.parse !== 'function') {
406                          JSON.parse = function (text, reviver) {
407                  
408                  // The parse method takes a text and an optional reviver function, and returns
409                  // a JavaScript value if the text is a valid JSON text.
410                  
411                              var j;
412                  
413                              function walk(holder, key) {
414                  
415                  // The walk method is used to recursively walk the resulting structure so
416                  // that modifications can be made.
417                  
418                                  var k, v, value = holder[key];
419                                  if (value && typeof value === 'object') {
420                                      for (k in value) {
421 lawrence.luo 1.2                         if (Object.prototype.hasOwnProperty.call(value, k)) {
422                                              v = walk(value, k);
423                                              if (v !== undefined) {
424                                                  value[k] = v;
425                                              } else {
426                                                  delete value[k];
427                                              }
428                                          }
429                                      }
430                                  }
431                                  return reviver.call(holder, key, value);
432                              }
433                  
434                  
435                  // Parsing happens in four stages. In the first stage, we replace certain
436                  // Unicode characters with escape sequences. JavaScript handles many characters
437                  // incorrectly, either silently deleting them, or treating them as line endings.
438                  
439                              text = String(text);
440                              cx.lastIndex = 0;
441                              if (cx.test(text)) {
442 lawrence.luo 1.2                 text = text.replace(cx, function (a) {
443                                      return '\\u' +
444                                          ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
445                                  });
446                              }
447                  
448                  // In the second stage, we run the text against regular expressions that look
449                  // for non-JSON patterns. We are especially concerned with '()' and 'new'
450                  // because they can cause invocation, and '=' because it can cause mutation.
451                  // But just to be safe, we want to reject all unexpected forms.
452                  
453                  // We split the second stage into 4 regexp operations in order to work around
454                  // crippling inefficiencies in IE's and Safari's regexp engines. First we
455                  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
456                  // replace all simple value tokens with ']' characters. Third, we delete all
457                  // open brackets that follow a colon or comma or that begin the text. Finally,
458                  // we look to see that the remaining characters are only whitespace or ']' or
459                  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
460                  
461                              if (/^[\],:{}\s]*$/
462                                      .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
463 lawrence.luo 1.2                         .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
464                                          .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
465                  
466                  // In the third stage we use the eval function to compile the text into a
467                  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
468                  // in JavaScript: it can begin a block or an object literal. We wrap the text
469                  // in parens to eliminate the ambiguity.
470                  
471                                  j = eval('(' + text + ')');
472                  
473                  // In the optional fourth stage, we recursively walk the new structure, passing
474                  // each name/value pair to a reviver function for possible transformation.
475                  
476                                  return typeof reviver === 'function'
477                                      ? walk({'': j}, '')
478                                      : j;
479                              }
480                  
481                  // If the text is not JSON parseable, then a SyntaxError is thrown.
482                  
483                              throw new SyntaxError('JSON.parse');
484 lawrence.luo 1.2         };
485                      }
486                  }());

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2