//@tag foundation,core //@define Ext.JSON //@require Ext.Function /** * @class Ext.JSON * ダグラス・クロックフォードによるjson.jsの修正版。Objectプロトタイプには変更なし。[http://www.json.org/js.html](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)) { if (Ext.isMSDate(o)) { return encodeMSDate(o); } else { 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(""); }, encodeMSDate = function(o) { return '"' + o + '"'; }; /** * 日付をエンコードします。これはリテラル表現としてJSON文字列に挿入される実際の文字列を返します。返される値はダブルクォーテーションで囲まれます。 * * デフォルトの戻り値のフォーマットは"yyyy-mm-ddThh:mm:ss"です。 * * これをオーバライドするには: * * Ext.JSON.encodeDate = function(d) { * return Ext.Date.format(d, '"Y-m-d"'); * }; * * @param {Date} d エンコードされる日付。 * @return {String} JSON文字列で使用する文字列リテラル。 */ this.encodeDate = function(o) { return '"' + o.getFullYear() + "-" + pad(o.getMonth() + 1) + "-" + pad(o.getDate()) + "T" + pad(o.getHours()) + ":" + pad(o.getMinutes()) + ":" + pad(o.getSeconds()) + '"'; }; /** * オブジェクトや配列、その他の値をエンコードします。 * @param {Object} o エンコードする変数 * @return {String} JSON文字列 * @method */ this.encode = function() { var ec; return function(o) { if (!ec) { // setup encoding function on first access ec = isNative() ? JSON.stringify : doEncode; } return ec(o); }; }(); /** * JSON文字列をオブジェクトにデコード(パース)します。JSONが無効なものならば、safeオプションを設定していない場合、関数はErrorをスローします。 * @param {String} json JSON文字列 * @param {Boolean} safe (optional) JSONが有効でない場合に、`null`を返すか、それとも、例外をスローするか。 * @return {Object/null} 結果のオブジェクト * @method */ 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 an invalid JSON String: " + json }); } }; }(); })(); /** * {@link Ext.JSON#encode}の短縮形です。 * @member Ext * @method encode * @alias Ext.JSON#encode */ Ext.encode = Ext.JSON.encode; /** * {@link Ext.JSON#decode}の短縮形です。 * @member Ext * @method decode * @alias Ext.JSON#decode */ Ext.decode = Ext.JSON.decode;