json-stringify.js revision 481402e2c2b8e4d633d9c023579d0250205ccc8e
// Regex used to capture characters that need escaping before enclosing // their containing string in quotes. _SPECIAL_CHARS = /[\\\
"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, // Character substitution map for common escapes and special characters. // Utility function used to determine how to serialize a variable. return _allowable[t] || // number, string, boolean, undefined _allowable[_toStr.call(o)] || // Number, String, Boolean, Date (o ? OBJECT : NULL) : // object, array, null, misc natives UNDEFINED); // function, unknown // Escapes a special character to a safe Unicode representation _CHARS[c] = '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4); // Enclose escaped strings in quotes return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE; // Adds the provided space to the beginning of every line in the input string function _indent(s,space) { return s.replace(/^/gm, space); // JavaScript implementation of stringify (see API declaration of stringify) function _stringify(o,w,space) { var replacer = isFunction(w) ? w : null, format = _toStr.call(space).match(/String|Number/) || [], _date = Y.JSON.dateToString, if (replacer || !isArray(w)) { // Ensure whitelist keys are unique (bug 2110391) for (i = 0, len = w.length; i < len; ++i) { // Per the spec, strings are truncated to 10 characters and numbers // are converted to that number of spaces (max 10) space = format[0] === 'Number' ? new Array(Math.min(Math.max(0,space),10)+1).join(" ") : (space || EMPTY).slice(0,10); function _serialize(h,key) { var o = isFunction(replacer) ? replacer.call(h,key,h[key]) : h[key], colon = space ? COLON_SP : COLON, case STRING : return _string(o); case NUMBER : return isFinite(o) ? o+EMPTY : NULL; case BOOLEAN : return o+EMPTY; case DATE : return _date(o); default : return undefined; // Check for cyclical references in nested objects for (i = stack.length - 1; i >= 0; --i) { // Add the object to the processing stack for (i = o.length - 1; i >= 0; --i) { a[i] = _serialize(o, i) || NULL; // If whitelist provided, take only those keys if (keys.hasOwnProperty(k)) { a[i++] = _string(k) + colon + v; // remove the array from the stack OPEN_A + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_A : OPEN_O + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_O; OPEN_A + a.join(COMMA) + CLOSE_A : OPEN_O + a.join(COMMA) + CLOSE_O; return _serialize({'':o},''); Y.mix(Y.namespace('JSON'),{ * Leverage native JSON stringify if the browser has a native * implementation. In general, this is a good idea. See the Known Issues * section in the JSON user guide for caveats. The default value is true * for browsers with native JSON support. * @property JSON.useNativeStringify useNativeStringify : !!Native, * Serializes a Date instance as a UTC date string. Used internally by * stringify. Override this method if you need Dates serialized in a * @param d {Date} The Date to serialize * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ dateToString : function (d) { return v < 10 ? '0' + v : v; return QUOTE + d.getUTCFullYear() + '-' + _zeroPad(d.getUTCMonth() + 1) + '-' + _zeroPad(d.getUTCDate()) + 'T' + _zeroPad(d.getUTCHours()) + COLON + _zeroPad(d.getUTCMinutes()) + COLON + _zeroPad(d.getUTCSeconds()) + 'Z' + QUOTE; * <p>Converts an arbitrary value to a JSON string representation.</p> * <p>Objects with cyclical references will trigger an exception.</p> * <p>If a whitelist is provided, only matching object keys will be * included. Alternately, a replacer function may be passed as the * second parameter. This function is executed on every value in the * input, and its return value will be used in place of the original value. * This is useful to serialize specialized objects or class instances.</p> * <p>If a positive integer or non-empty string is passed as the third * parameter, the output will be formatted with carriage returns and * indentation for readability. If a String is passed (such as "\t
") it * will be used once for each indentation level. If a number is passed, * that number of spaces will be used.</p> * @param o {MIXED} any arbitrary value to convert to JSON string * @param w {Array|Function} (optional) whitelist of acceptable object * keys to include, or a replacer function to modify the * raw value before serialization * @param ind {Number|String} (optional) indentation character or depth of * spaces to format the output. * @return {string} JSON string representation of the input stringify : function (o,w,ind) { return Native && Y.JSON.useNativeStringify ? Native.stringify(o,w,ind) : _stringify(o,w,ind);