mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 15:40:22 +00:00
205 lines
5.5 KiB
JavaScript
205 lines
5.5 KiB
JavaScript
'use strict';
|
|
|
|
var array = [].constructor;
|
|
|
|
/**
|
|
* @ngdoc function
|
|
* @name angular.toJson
|
|
* @function
|
|
*
|
|
* @description
|
|
* Serializes input into a JSON-formatted string.
|
|
*
|
|
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
|
|
* @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
|
|
* @returns {string} Jsonified string representing `obj`.
|
|
*/
|
|
function toJson(obj, pretty) {
|
|
var buf = [];
|
|
toJsonArray(buf, obj, pretty ? "\n " : null, []);
|
|
return buf.join('');
|
|
}
|
|
|
|
/**
|
|
* @ngdoc function
|
|
* @name angular.fromJson
|
|
* @function
|
|
*
|
|
* @description
|
|
* Deserializes a JSON string.
|
|
*
|
|
* @param {string} json JSON string to deserialize.
|
|
* @param {boolean} [useNative=false] Use native JSON parser, if available.
|
|
* @returns {Object|Array|Date|string|number} Deserialized thingy.
|
|
*/
|
|
function fromJson(json, useNative) {
|
|
if (!isString(json)) return json;
|
|
|
|
var obj;
|
|
|
|
try {
|
|
if (useNative && window.JSON && window.JSON.parse) {
|
|
obj = JSON.parse(json);
|
|
} else {
|
|
obj = parseJson(json, true)();
|
|
}
|
|
return transformDates(obj);
|
|
} catch (e) {
|
|
error("fromJson error: ", json, e);
|
|
throw e;
|
|
}
|
|
|
|
// TODO make forEach optionally recursive and remove this function
|
|
// TODO(misko): remove this once the $http service is checked in.
|
|
function transformDates(obj) {
|
|
if (isString(obj) && obj.length === DATE_ISOSTRING_LN) {
|
|
return jsonStringToDate(obj);
|
|
} else if (isArray(obj) || isObject(obj)) {
|
|
forEach(obj, function(val, name) {
|
|
obj[name] = transformDates(val);
|
|
});
|
|
}
|
|
return obj;
|
|
}
|
|
}
|
|
|
|
var R_ISO8061_STR = /^(\d{4})-(\d\d)-(\d\d)(?:T(\d\d)(?:\:(\d\d)(?:\:(\d\d)(?:\.(\d{3}))?)?)?Z)?$/;
|
|
function jsonStringToDate(string){
|
|
var match;
|
|
if (isString(string) && (match = string.match(R_ISO8061_STR))){
|
|
var date = new Date(0);
|
|
date.setUTCFullYear(match[1], match[2] - 1, match[3]);
|
|
date.setUTCHours(match[4]||0, match[5]||0, match[6]||0, match[7]||0);
|
|
return date;
|
|
}
|
|
return string;
|
|
}
|
|
|
|
function jsonDateToString(date){
|
|
if (!date) return date;
|
|
var isoString = date.toISOString ? date.toISOString() : '';
|
|
return (isoString.length==24)
|
|
? isoString
|
|
: padNumber(date.getUTCFullYear(), 4) + '-' +
|
|
padNumber(date.getUTCMonth() + 1, 2) + '-' +
|
|
padNumber(date.getUTCDate(), 2) + 'T' +
|
|
padNumber(date.getUTCHours(), 2) + ':' +
|
|
padNumber(date.getUTCMinutes(), 2) + ':' +
|
|
padNumber(date.getUTCSeconds(), 2) + '.' +
|
|
padNumber(date.getUTCMilliseconds(), 3) + 'Z';
|
|
}
|
|
|
|
function quoteUnicode(string) {
|
|
var chars = ['"'];
|
|
for ( var i = 0; i < string.length; i++) {
|
|
var code = string.charCodeAt(i);
|
|
var ch = string.charAt(i);
|
|
switch(ch) {
|
|
case '"': chars.push('\\"'); break;
|
|
case '\\': chars.push('\\\\'); break;
|
|
case '\n': chars.push('\\n'); break;
|
|
case '\f': chars.push('\\f'); break;
|
|
case '\r': chars.push(ch = '\\r'); break;
|
|
case '\t': chars.push(ch = '\\t'); break;
|
|
default:
|
|
if (32 <= code && code <= 126) {
|
|
chars.push(ch);
|
|
} else {
|
|
var encode = "000" + code.toString(16);
|
|
chars.push("\\u" + encode.substring(encode.length - 4));
|
|
}
|
|
}
|
|
}
|
|
chars.push('"');
|
|
return chars.join('');
|
|
}
|
|
|
|
|
|
function toJsonArray(buf, obj, pretty, stack) {
|
|
if (isObject(obj)) {
|
|
if (obj === window) {
|
|
buf.push('WINDOW');
|
|
return;
|
|
}
|
|
|
|
if (obj === document) {
|
|
buf.push('DOCUMENT');
|
|
return;
|
|
}
|
|
|
|
if (includes(stack, obj)) {
|
|
buf.push('RECURSION');
|
|
return;
|
|
}
|
|
stack.push(obj);
|
|
}
|
|
if (obj === null) {
|
|
buf.push('null');
|
|
} else if (obj instanceof RegExp) {
|
|
buf.push(quoteUnicode(obj.toString()));
|
|
} else if (isFunction(obj)) {
|
|
return;
|
|
} else if (isBoolean(obj)) {
|
|
buf.push('' + obj);
|
|
} else if (isNumber(obj)) {
|
|
if (isNaN(obj)) {
|
|
buf.push('null');
|
|
} else {
|
|
buf.push('' + obj);
|
|
}
|
|
} else if (isString(obj)) {
|
|
return buf.push(quoteUnicode(obj));
|
|
} else if (isObject(obj)) {
|
|
if (isArray(obj)) {
|
|
buf.push("[");
|
|
var len = obj.length;
|
|
var sep = false;
|
|
for(var i=0; i<len; i++) {
|
|
var item = obj[i];
|
|
if (sep) buf.push(",");
|
|
if (!(item instanceof RegExp) && (isFunction(item) || isUndefined(item))) {
|
|
buf.push('null');
|
|
} else {
|
|
toJsonArray(buf, item, pretty, stack);
|
|
}
|
|
sep = true;
|
|
}
|
|
buf.push("]");
|
|
} else if (isElement(obj)) {
|
|
// TODO(misko): maybe in dev mode have a better error reporting?
|
|
buf.push('DOM_ELEMENT');
|
|
} else if (isDate(obj)) {
|
|
buf.push(quoteUnicode(jsonDateToString(obj)));
|
|
} else {
|
|
buf.push("{");
|
|
if (pretty) buf.push(pretty);
|
|
var comma = false;
|
|
var childPretty = pretty ? pretty + " " : false;
|
|
var keys = [];
|
|
for(var k in obj) {
|
|
if (k!='this' && k!='$parent' && k.substring(0,2) != '$$' && obj.hasOwnProperty(k) && obj[k] !== undefined) {
|
|
keys.push(k);
|
|
}
|
|
}
|
|
keys.sort();
|
|
for ( var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
|
|
var key = keys[keyIndex];
|
|
var value = obj[key];
|
|
if (!isFunction(value)) {
|
|
if (comma) {
|
|
buf.push(",");
|
|
if (pretty) buf.push(pretty);
|
|
}
|
|
buf.push(quoteUnicode(key));
|
|
buf.push(":");
|
|
toJsonArray(buf, value, childPretty, stack);
|
|
comma = true;
|
|
}
|
|
}
|
|
buf.push("}");
|
|
}
|
|
}
|
|
if (isObject(obj)) {
|
|
stack.pop();
|
|
}
|
|
}
|