[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-json/ -> yui2-json.js (source)

   1  YUI.add('yui2-json', function(Y) {
   2      var YAHOO    = Y.YUI2;
   3      /*
   4  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
   5  Code licensed under the BSD License:
   6  http://developer.yahoo.com/yui/license.html
   7  version: 2.9.0
   8  */
   9  /**
  10   * Provides methods to parse JSON strings and convert objects to JSON strings.
  11   *
  12   * @module json
  13   * @class JSON
  14   * @namespace YAHOO.lang
  15   * @static
  16   */
  17  (function () {
  18  
  19  var l = YAHOO.lang,
  20      isFunction = l.isFunction,
  21      isObject   = l.isObject,
  22      isArray    = l.isArray,
  23      _toStr     = Object.prototype.toString,
  24                   // 'this' is the global object.  window in browser env.  Keep
  25                   // the code env agnostic.  Caja requies window, unfortunately.
  26      Native     = (YAHOO.env.ua.caja ? window : this).JSON,
  27  
  28  /* Variables used by parse */
  29  
  30      /**
  31       * Replace certain Unicode characters that JavaScript may handle incorrectly
  32       * during eval--either by deleting them or treating them as line
  33       * endings--with escape sequences.
  34       * IMPORTANT NOTE: This regex will be used to modify the input if a match is
  35       * found.
  36       *
  37       * @property _UNICODE_EXCEPTIONS
  38       * @type {RegExp}
  39       * @private
  40       */
  41      _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
  42  
  43      /**
  44       * First step in the safety evaluation.  Regex used to replace all escape
  45       * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
  46       *
  47       * @property _ESCAPES
  48       * @type {RegExp}
  49       * @static
  50       * @private
  51       */
  52      _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
  53  
  54      /**
  55       * Second step in the safety evaluation.  Regex used to replace all simple
  56       * values with ']' characters.
  57       *
  58       * @property _VALUES
  59       * @type {RegExp}
  60       * @static
  61       * @private
  62       */
  63      _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
  64  
  65      /**
  66       * Third step in the safety evaluation.  Regex used to remove all open
  67       * square brackets following a colon, comma, or at the beginning of the
  68       * string.
  69       *
  70       * @property _BRACKETS
  71       * @type {RegExp}
  72       * @static
  73       * @private
  74       */
  75      _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
  76  
  77      /**
  78       * Final step in the safety evaluation.  Regex used to test the string left
  79       * after all previous replacements for invalid characters.
  80       *
  81       * @property _UNSAFE
  82       * @type {RegExp}
  83       * @static
  84       * @private
  85       */
  86      _UNSAFE  = /[^\],:{}\s]/,
  87  
  88  
  89  /* Variables used by stringify */
  90  
  91      /**
  92       * Regex used to replace special characters in strings for JSON
  93       * stringification.
  94       *
  95       * @property _SPECIAL_CHARS
  96       * @type {RegExp}
  97       * @static
  98       * @private
  99       */
 100      _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 101  
 102      /**
 103       * Character substitution map for common escapes and special characters.
 104       *
 105       * @property _CHARS
 106       * @type {Object}
 107       * @static
 108       * @private
 109       */
 110      _CHARS = {
 111          '\b': '\\b',
 112          '\t': '\\t',
 113          '\n': '\\n',
 114          '\f': '\\f',
 115          '\r': '\\r',
 116          '"' : '\\"',
 117          '\\': '\\\\'
 118      },
 119      
 120      UNDEFINED = 'undefined',
 121      OBJECT    = 'object',
 122      NULL      = 'null',
 123      STRING    = 'string',
 124      NUMBER    = 'number',
 125      BOOLEAN   = 'boolean',
 126      DATE      = 'date',
 127      _allowable = {
 128          'undefined'        : UNDEFINED,
 129          'string'           : STRING,
 130          '[object String]'  : STRING,
 131          'number'           : NUMBER,
 132          '[object Number]'  : NUMBER,
 133          'boolean'          : BOOLEAN,
 134          '[object Boolean]' : BOOLEAN,
 135          '[object Date]'    : DATE,
 136          '[object RegExp]'  : OBJECT
 137      },
 138      EMPTY     = '',
 139      OPEN_O    = '{',
 140      CLOSE_O   = '}',
 141      OPEN_A    = '[',
 142      CLOSE_A   = ']',
 143      COMMA     = ',',
 144      COMMA_CR  = ",\n",
 145      CR        = "\n",
 146      COLON     = ':',
 147      COLON_SP  = ': ',
 148      QUOTE     = '"';
 149  
 150  // Only accept JSON objects that report a [[Class]] of JSON
 151  Native = _toStr.call(Native) === '[object JSON]' && Native;
 152  
 153  // Escapes a special character to a safe Unicode representation
 154  function _char(c) {
 155      if (!_CHARS[c]) {
 156          _CHARS[c] =  '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
 157      }
 158      return _CHARS[c];
 159  }
 160  
 161  
 162  /* functions used by parse */
 163  
 164  /**
 165   * Traverses nested objects, applying a filter or reviver function to
 166   * each value.  The value returned from the function will replace the
 167   * original value in the key:value pair.  If the value returned is
 168   * undefined, the key will be omitted from the returned object.
 169   *
 170   * @method _revive
 171   * @param data {MIXED} Any JavaScript data
 172   * @param reviver {Function} filter or mutation function
 173   * @return {MIXED} The results of the filtered/mutated data structure
 174   * @private
 175   */
 176  function _revive(data, reviver) {
 177      var walk = function (o,key) {
 178          var k,v,value = o[key];
 179          if (value && typeof value === 'object') {
 180              for (k in value) {
 181                  if (l.hasOwnProperty(value,k)) {
 182                      v = walk(value, k);
 183                      if (v === undefined) {
 184                          delete value[k];
 185                      } else {
 186                          value[k] = v;
 187                      }
 188                  }
 189              }
 190          }
 191          return reviver.call(o,key,value);
 192      };
 193  
 194      return typeof reviver === 'function' ? walk({'':data},'') : data;
 195  }
 196  
 197  /**
 198   * Replace certain Unicode characters that may be handled incorrectly by
 199   * some browser implementations.
 200   *
 201   * @method _prepare
 202   * @param s {String} parse input
 203   * @return {String} sanitized JSON string ready to be validated/parsed
 204   * @private
 205   */
 206  function _prepare(s) {
 207      return s.replace(_UNICODE_EXCEPTIONS, _char);
 208  }
 209  
 210  function _isSafe(str) {
 211      return l.isString(str) &&
 212              !_UNSAFE.test(str.replace(_ESCAPES,'@').
 213                               replace(_VALUES,']').
 214                               replace(_BRACKETS,''));
 215  }
 216  
 217  function _parse(s,reviver) {
 218      // sanitize
 219      s = _prepare(s);
 220  
 221      // Ensure valid JSON
 222      if (_isSafe(s)) {
 223          // Eval the text into a JavaScript data structure, apply the
 224          // reviver function if provided, and return
 225          return _revive( eval('(' + s + ')'), reviver );
 226      }
 227  
 228      // The text is not valid JSON
 229      throw new SyntaxError('JSON.parse');
 230  }
 231  
 232  
 233  
 234  /* functions used by stringify */
 235  
 236  // Utility function used to determine how to serialize a variable.
 237  function _type(o) {
 238      var t = typeof o;
 239      return  _allowable[t] ||              // number, string, boolean, undefined
 240              _allowable[_toStr.call(o)] || // Number, String, Boolean, Date
 241              (t === OBJECT ?
 242                  (o ? OBJECT : NULL) :     // object, array, null, misc natives
 243                  UNDEFINED);               // function, unknown
 244  }
 245  
 246  // Enclose escaped strings in quotes
 247  function _string(s) {
 248      return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE;
 249  }
 250  
 251  // Adds the provided space to the beginning of every line in the input string
 252  function _indent(s,space) {
 253      return s.replace(/^/gm, space);
 254  }
 255  
 256  // JavaScript implementation of stringify (see API declaration of stringify)
 257  function _stringify(o,w,space) {
 258      if (o === undefined) {
 259          return undefined;
 260      }
 261  
 262      var replacer = isFunction(w) ? w : null,
 263          format   = _toStr.call(space).match(/String|Number/) || [],
 264          _date    = YAHOO.lang.JSON.dateToString,
 265          stack    = [],
 266          tmp,i,len;
 267  
 268      if (replacer || !isArray(w)) {
 269          w = undefined;
 270      }
 271  
 272      // Ensure whitelist keys are unique (bug 2110391)
 273      if (w) {
 274          tmp = {};
 275          for (i = 0, len = w.length; i < len; ++i) {
 276              tmp[w[i]] = true;
 277          }
 278          w = tmp;
 279      }
 280  
 281      // Per the spec, strings are truncated to 10 characters and numbers
 282      // are converted to that number of spaces (max 10)
 283      space = format[0] === 'Number' ?
 284                  new Array(Math.min(Math.max(0,space),10)+1).join(" ") :
 285                  (space || EMPTY).slice(0,10);
 286  
 287      function _serialize(h,key) {
 288          var value = h[key],
 289              t     = _type(value),
 290              a     = [],
 291              colon = space ? COLON_SP : COLON,
 292              arr, i, keys, k, v;
 293  
 294          // Per the ECMA 5 spec, toJSON is applied before the replacer is
 295          // called.  Also per the spec, Date.prototype.toJSON has been added, so
 296          // Date instances should be serialized prior to exposure to the
 297          // replacer.  I disagree with this decision, but the spec is the spec.
 298          if (isObject(value) && isFunction(value.toJSON)) {
 299              value = value.toJSON(key);
 300          } else if (t === DATE) {
 301              value = _date(value);
 302          }
 303  
 304          if (isFunction(replacer)) {
 305              value = replacer.call(h,key,value);
 306          }
 307  
 308          if (value !== h[key]) {
 309              t = _type(value);
 310          }
 311  
 312          switch (t) {
 313              case DATE    : // intentional fallthrough.  Pre-replacer Dates are
 314                             // serialized in the toJSON stage.  Dates here would
 315                             // have been produced by the replacer.
 316              case OBJECT  : break;
 317              case STRING  : return _string(value);
 318              case NUMBER  : return isFinite(value) ? value+EMPTY : NULL;
 319              case BOOLEAN : return value+EMPTY;
 320              case NULL    : return NULL;
 321              default      : return undefined;
 322          }
 323  
 324          // Check for cyclical references in nested objects
 325          for (i = stack.length - 1; i >= 0; --i) {
 326              if (stack[i] === value) {
 327                  throw new Error("JSON.stringify. Cyclical reference");
 328              }
 329          }
 330  
 331          arr = isArray(value);
 332  
 333          // Add the object to the processing stack
 334          stack.push(value);
 335  
 336          if (arr) { // Array
 337              for (i = value.length - 1; i >= 0; --i) {
 338                  a[i] = _serialize(value, i) || NULL;
 339              }
 340          } else {   // Object
 341              // If whitelist provided, take only those keys
 342              keys = w || value;
 343              i = 0;
 344  
 345              for (k in keys) {
 346                  if (l.hasOwnProperty(keys, k)) {
 347                      v = _serialize(value, k);
 348                      if (v) {
 349                          a[i++] = _string(k) + colon + v;
 350                      }
 351                  }
 352              }
 353          }
 354  
 355          // remove the array from the stack
 356          stack.pop();
 357  
 358          if (space && a.length) {
 359              return arr ?
 360                  OPEN_A + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_A :
 361                  OPEN_O + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_O;
 362          } else {
 363              return arr ?
 364                  OPEN_A + a.join(COMMA) + CLOSE_A :
 365                  OPEN_O + a.join(COMMA) + CLOSE_O;
 366          }
 367      }
 368  
 369      // process the input
 370      return _serialize({'':o},'');
 371  }
 372  
 373  
 374  /* Public API */
 375  YAHOO.lang.JSON = {
 376      /**
 377       * Leverage native JSON parse if the browser has a native implementation.
 378       * In general, this is a good idea.  See the Known Issues section in the
 379       * JSON user guide for caveats.  The default value is true for browsers with
 380       * native JSON support.
 381       *
 382       * @property useNativeParse
 383       * @type Boolean
 384       * @default true
 385       * @static
 386       */
 387      useNativeParse : !!Native,
 388  
 389      /**
 390       * Leverage native JSON stringify if the browser has a native
 391       * implementation.  In general, this is a good idea.  See the Known Issues
 392       * section in the JSON user guide for caveats.  The default value is true
 393       * for browsers with native JSON support.
 394       *
 395       * @property useNativeStringify
 396       * @type Boolean
 397       * @default true
 398       * @static
 399       */
 400      useNativeStringify : !!Native,
 401  
 402      /**
 403       * Four step determination whether a string is safe to eval. In three steps,
 404       * escape sequences, safe values, and properly placed open square brackets
 405       * are replaced with placeholders or removed.  Then in the final step, the
 406       * result of all these replacements is checked for invalid characters.
 407       *
 408       * @method isSafe
 409       * @param str {String} JSON string to be tested
 410       * @return {boolean} is the string safe for eval?
 411       * @static
 412       */
 413      isSafe : function (s) {
 414          return _isSafe(_prepare(s));
 415      },
 416  
 417      /**
 418       * <p>Parse a JSON string, returning the native JavaScript
 419       * representation.</p>
 420       *
 421       * <p>When lang.JSON.useNativeParse is true, this will defer to the native
 422       * JSON.parse if the browser has a native implementation.  Otherwise, a
 423       * JavaScript implementation based on http://www.json.org/json2.js
 424       * is used.</p>
 425       *
 426       * @method parse
 427       * @param s {string} JSON string data
 428       * @param reviver {function} (optional) function(k,v) passed each key:value
 429       *          pair of object literals, allowing pruning or altering values
 430       * @return {MIXED} the native JavaScript representation of the JSON string
 431       * @throws SyntaxError
 432       * @static
 433       */
 434      parse : function (s,reviver) {
 435          if (typeof s !== 'string') {
 436              s += '';
 437          }
 438  
 439          return Native && YAHOO.lang.JSON.useNativeParse ?
 440              Native.parse(s,reviver) : _parse(s,reviver);
 441      },
 442  
 443      /**
 444       * <p>Converts an arbitrary value to a JSON string representation.</p>
 445       *
 446       * <p>Objects with cyclical references will trigger an exception.</p>
 447       *
 448       * <p>If a whitelist is provided, only matching object keys will be
 449       * included.  Alternately, a replacer function may be passed as the
 450       * second parameter.  This function is executed on every value in the
 451       * input, and its return value will be used in place of the original value.
 452       * This is useful to serialize specialized objects or class instances.</p>
 453       *
 454       * <p>If a positive integer or non-empty string is passed as the third
 455       * parameter, the output will be formatted with carriage returns and
 456       * indentation for readability.  If a String is passed (such as "\t") it
 457       * will be used once for each indentation level.  If a number is passed,
 458       * that number of spaces will be used.</p>
 459       *
 460       * <p>When lang.JSON.useNativeStringify is true, this will defer to the
 461       * native JSON.stringify if the browser has a native implementation.
 462       * Otherwise, a JavaScript implementation is used.</p>
 463       *
 464       * @method stringify
 465       * @param o {MIXED} any arbitrary object to convert to JSON string
 466       * @param w {Array|Function} (optional) whitelist of acceptable object keys
 467       *                  to include OR a function(value,key) to alter values
 468       *                  before serialization
 469       * @param space {Number|String} (optional) indentation character(s) or
 470       *                  depthy of spaces to format the output 
 471       * @return {string} JSON string representation of the input
 472       * @throws Error
 473       * @static
 474       */
 475      stringify : function (o,w,space) {
 476          return Native && YAHOO.lang.JSON.useNativeStringify ?
 477              Native.stringify(o,w,space) : _stringify(o,w,space);
 478      },
 479  
 480      /**
 481       * Serializes a Date instance as a UTC date string.  Used internally by
 482       * the JavaScript implementation of stringify.  If you need a different
 483       * Date serialization format, override this method.  If you change this,
 484       * you should also set useNativeStringify to false, since native JSON
 485       * implementations serialize Dates per the ECMAScript 5 spec.  You've been
 486       * warned.
 487       *
 488       * @method dateToString
 489       * @param d {Date} The Date to serialize
 490       * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
 491       * @static
 492       */
 493      dateToString : function (d) {
 494          function _zeroPad(v) {
 495              return v < 10 ? '0' + v : v;
 496          }
 497  
 498          return d.getUTCFullYear()         + '-' +
 499              _zeroPad(d.getUTCMonth() + 1) + '-' +
 500              _zeroPad(d.getUTCDate())      + 'T' +
 501              _zeroPad(d.getUTCHours())     + COLON +
 502              _zeroPad(d.getUTCMinutes())   + COLON +
 503              _zeroPad(d.getUTCSeconds())   + 'Z';
 504      },
 505  
 506      /**
 507       * Reconstitute Date instances from the default JSON UTC serialization.
 508       * Reference this from a reviver function to rebuild Dates during the
 509       * parse operation.
 510       *
 511       * @method stringToDate
 512       * @param str {String} String serialization of a Date
 513       * @return {Date}
 514       */
 515      stringToDate : function (str) {
 516          var m = str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/);
 517          if (m) {
 518              var d = new Date();
 519              d.setUTCFullYear(m[1], m[2]-1, m[3]);
 520              d.setUTCHours(m[4], m[5], m[6], (m[7] || 0));
 521              return d;
 522          }
 523          return str;
 524      }
 525  };
 526  
 527  /**
 528   * <p>Four step determination whether a string is safe to eval. In three steps,
 529   * escape sequences, safe values, and properly placed open square brackets
 530   * are replaced with placeholders or removed.  Then in the final step, the
 531   * result of all these replacements is checked for invalid characters.</p>
 532   *
 533   * <p>This is an alias for isSafe.</p>
 534   *
 535   * @method isValid
 536   * @param str {String} JSON string to be tested
 537   * @return {boolean} is the string safe for eval?
 538   * @static
 539   * @deprecated use isSafe
 540   */
 541  YAHOO.lang.JSON.isValid = YAHOO.lang.JSON.isSafe;
 542  
 543  })();
 544  YAHOO.register("json", YAHOO.lang.JSON, {version: "2.9.0", build: "2800"});
 545  
 546  }, '2.9.0' ,{"requires": ["yui2-yahoo"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1