X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/core/src/misc/JSON.js diff --git a/src/core/src/misc/JSON.js b/src/core/src/misc/JSON.js new file mode 100644 index 00000000..356371b6 --- /dev/null +++ b/src/core/src/misc/JSON.js @@ -0,0 +1,175 @@ +/** + * @class Ext.JSON + * Modified version of Douglas Crockford"s json.js that doesn"t + * mess with the Object prototype + * http://www.json.org/js.html + * @singleton + */ +Ext.JSON = new(function() { + var useHasOwn = !! {}.hasOwnProperty, + isNative = function() { + var useNative = null; + + return function() { + if (useNative === null) { + useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]'; + } + + return useNative; + }; + }(), + pad = function(n) { + return n < 10 ? "0" + n : n; + }, + doDecode = function(json) { + return eval("(" + json + ')'); + }, + doEncode = function(o) { + if (!Ext.isDefined(o) || o === null) { + return "null"; + } else if (Ext.isArray(o)) { + return encodeArray(o); + } else if (Ext.isDate(o)) { + return Ext.JSON.encodeDate(o); + } else if (Ext.isString(o)) { + return encodeString(o); + } else if (typeof o == "number") { + //don't use isNumber here, since finite checks happen inside isNumber + return isFinite(o) ? String(o) : "null"; + } else if (Ext.isBoolean(o)) { + return String(o); + } else if (Ext.isObject(o)) { + return encodeObject(o); + } else if (typeof o === "function") { + return "null"; + } + return 'undefined'; + }, + m = { + "\b": '\\b', + "\t": '\\t', + "\n": '\\n', + "\f": '\\f', + "\r": '\\r', + '"': '\\"', + "\\": '\\\\', + '\x0b': '\\u000b' //ie doesn't handle \v + }, + charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g, + encodeString = function(s) { + return '"' + s.replace(charToReplace, function(a) { + var c = m[a]; + return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"'; + }, + encodeArray = function(o) { + var a = ["[", ""], + // Note empty string in case there are no serializable members. + len = o.length, + i; + for (i = 0; i < len; i += 1) { + a.push(doEncode(o[i]), ','); + } + // Overwrite trailing comma (or empty string) + a[a.length - 1] = ']'; + return a.join(""); + }, + encodeObject = function(o) { + var a = ["{", ""], + // Note empty string in case there are no serializable members. + i; + for (i in o) { + if (!useHasOwn || o.hasOwnProperty(i)) { + a.push(doEncode(i), ":", doEncode(o[i]), ','); + } + } + // Overwrite trailing comma (or empty string) + a[a.length - 1] = '}'; + return a.join(""); + }; + + /** + *

Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression. + * The returned value includes enclosing double quotation marks.

+ *

The default return format is "yyyy-mm-ddThh:mm:ss".

+ *

To override this:


+     Ext.JSON.encodeDate = function(d) {
+     return d.format('"Y-m-d"');
+     };
+     
+ * @param {Date} d The Date to encode + * @return {String} The string literal to use in a JSON string. + */ + this.encodeDate = function(o) { + return '"' + o.getFullYear() + "-" + + pad(o.getMonth() + 1) + "-" + + pad(o.getDate()) + "T" + + pad(o.getHours()) + ":" + + pad(o.getMinutes()) + ":" + + pad(o.getSeconds()) + '"'; + }; + + /** + * Encodes an Object, Array or other value + * @param {Mixed} o The variable to encode + * @return {String} The JSON string + */ + this.encode = function() { + var ec; + return function(o) { + if (!ec) { + // setup encoding function on first access + ec = isNative() ? JSON.stringify : doEncode; + } + return ec(o); + }; + }(); + + + /** + * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError unless the safe option is set. + * @param {String} json The JSON string + * @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid. + * @return {Object} The resulting object + */ + this.decode = function() { + var dc; + return function(json, safe) { + if (!dc) { + // setup decoding function on first access + dc = isNative() ? JSON.parse : doDecode; + } + try { + return dc(json); + } catch (e) { + if (safe === true) { + return null; + } + Ext.Error.raise({ + sourceClass: "Ext.JSON", + sourceMethod: "decode", + msg: "You're trying to decode and invalid JSON String: " + json + }); + } + }; + }(); + +})(); +/** + * Shorthand for {@link Ext.JSON#encode} + * @param {Mixed} o The variable to encode + * @return {String} The JSON string + * @member Ext + * @method encode + */ +Ext.encode = Ext.JSON.encode; +/** + * Shorthand for {@link Ext.JSON#decode} + * @param {String} json The JSON string + * @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid. + * @return {Object} The resulting object + * @member Ext + * @method decode + */ +Ext.decode = Ext.JSON.decode; +