You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.8 KiB
162 lines
5.8 KiB
define(["./has"], function(has){ |
|
"use strict"; |
|
var hasJSON = typeof JSON != "undefined"; |
|
has.add("json-parse", hasJSON); // all the parsers work fine |
|
// Firefox 3.5/Gecko 1.9 fails to use replacer in stringify properly https://bugzilla.mozilla.org/show_bug.cgi?id=509184 |
|
has.add("json-stringify", hasJSON && JSON.stringify({a:0}, function(k,v){return v||1;}) == '{"a":1}'); |
|
|
|
/*===== |
|
return { |
|
// summary: |
|
// Functions to parse and serialize JSON |
|
|
|
parse: function(str, strict){ |
|
// summary: |
|
// Parses a [JSON](http://json.org) string to return a JavaScript object. |
|
// description: |
|
// This function follows [native JSON API](https://developer.mozilla.org/en/JSON) |
|
// Throws for invalid JSON strings. This delegates to eval() if native JSON |
|
// support is not available. By default this will evaluate any valid JS expression. |
|
// With the strict parameter set to true, the parser will ensure that only |
|
// valid JSON strings are parsed (otherwise throwing an error). Without the strict |
|
// parameter, the content passed to this method must come |
|
// from a trusted source. |
|
// str: |
|
// a string literal of a JSON item, for instance: |
|
// `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'` |
|
// strict: |
|
// When set to true, this will ensure that only valid, secure JSON is ever parsed. |
|
// Make sure this is set to true for untrusted content. Note that on browsers/engines |
|
// without native JSON support, setting this to true will run slower. |
|
}, |
|
stringify: function(value, replacer, spacer){ |
|
// summary: |
|
// Returns a [JSON](http://json.org) serialization of an object. |
|
// description: |
|
// Returns a [JSON](http://json.org) serialization of an object. |
|
// This function follows [native JSON API](https://developer.mozilla.org/en/JSON) |
|
// Note that this doesn't check for infinite recursion, so don't do that! |
|
// value: |
|
// A value to be serialized. |
|
// replacer: |
|
// A replacer function that is called for each value and can return a replacement |
|
// spacer: |
|
// A spacer string to be used for pretty printing of JSON |
|
// example: |
|
// simple serialization of a trivial object |
|
// | define(["dojo/json"], function(JSON){ |
|
// | var jsonStr = JSON.stringify({ howdy: "stranger!", isStrange: true }); |
|
// | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr); |
|
} |
|
}; |
|
=====*/ |
|
|
|
if(has("json-stringify")){ |
|
return JSON; |
|
}else{ |
|
var escapeString = function(/*String*/str){ |
|
// summary: |
|
// Adds escape sequences for non-visual characters, double quote and |
|
// backslash and surrounds with double quotes to form a valid string |
|
// literal. |
|
return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'). |
|
replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n"). |
|
replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string |
|
}; |
|
return { |
|
parse: has("json-parse") ? JSON.parse : function(str, strict){ |
|
if(strict && !/^([\s\[\{]*(?:"(?:\\.|[^"])*"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){ |
|
throw new SyntaxError("Invalid characters in JSON"); |
|
} |
|
return eval('(' + str + ')'); |
|
}, |
|
stringify: function(value, replacer, spacer){ |
|
var undef; |
|
if(typeof replacer == "string"){ |
|
spacer = replacer; |
|
replacer = null; |
|
} |
|
function stringify(it, indent, key){ |
|
if(replacer){ |
|
it = replacer(key, it); |
|
} |
|
var val, objtype = typeof it; |
|
if(objtype == "number"){ |
|
return isFinite(it) ? it + "" : "null"; |
|
} |
|
if(objtype == "boolean"){ |
|
return it + ""; |
|
} |
|
if(it === null){ |
|
return "null"; |
|
} |
|
if(typeof it == "string"){ |
|
return escapeString(it); |
|
} |
|
if(objtype == "function" || objtype == "undefined"){ |
|
return undef; // undefined |
|
} |
|
// short-circuit for objects that support "json" serialization |
|
// if they return "self" then just pass-through... |
|
if(typeof it.toJSON == "function"){ |
|
return stringify(it.toJSON(key), indent, key); |
|
} |
|
if(it instanceof Date){ |
|
return '"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z"'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){ |
|
var num = it["getUTC" + prop]() + (plus ? 1 : 0); |
|
return num < 10 ? "0" + num : num; |
|
}); |
|
} |
|
if(it.valueOf() !== it){ |
|
// primitive wrapper, try again unwrapped: |
|
return stringify(it.valueOf(), indent, key); |
|
} |
|
var nextIndent= spacer ? (indent + spacer) : ""; |
|
/* we used to test for DOM nodes and throw, but FF serializes them as {}, so cross-browser consistency is probably not efficiently attainable */ |
|
|
|
var sep = spacer ? " " : ""; |
|
var newLine = spacer ? "\n" : ""; |
|
|
|
// array |
|
if(it instanceof Array){ |
|
var itl = it.length, res = []; |
|
for(key = 0; key < itl; key++){ |
|
var obj = it[key]; |
|
val = stringify(obj, nextIndent, key); |
|
if(typeof val != "string"){ |
|
val = "null"; |
|
} |
|
res.push(newLine + nextIndent + val); |
|
} |
|
return "[" + res.join(",") + newLine + indent + "]"; |
|
} |
|
// generic object code path |
|
var output = []; |
|
for(key in it){ |
|
var keyStr; |
|
if(it.hasOwnProperty(key)){ |
|
if(typeof key == "number"){ |
|
keyStr = '"' + key + '"'; |
|
}else if(typeof key == "string"){ |
|
keyStr = escapeString(key); |
|
}else{ |
|
// skip non-string or number keys |
|
continue; |
|
} |
|
val = stringify(it[key], nextIndent, key); |
|
if(typeof val != "string"){ |
|
// skip non-serializable values |
|
continue; |
|
} |
|
// At this point, the most non-IE browsers don't get in this branch |
|
// (they have native JSON), so push is definitely the way to |
|
output.push(newLine + nextIndent + keyStr + ":" + sep + val); |
|
} |
|
} |
|
return "{" + output.join(",") + newLine + indent + "}"; // String |
|
} |
|
return stringify(value, "", ""); |
|
} |
|
}; |
|
} |
|
});
|
|
|