source: Dev/trunk/src/client/dojo/json.js @ 501

Last change on this file since 501 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 5.8 KB
Line 
1define(["./has"], function(has){
2        "use strict";
3        var hasJSON = typeof JSON != "undefined";
4        has.add("json-parse", hasJSON); // all the parsers work fine
5                // Firefox 3.5/Gecko 1.9 fails to use replacer in stringify properly https://bugzilla.mozilla.org/show_bug.cgi?id=509184
6        has.add("json-stringify", hasJSON && JSON.stringify({a:0}, function(k,v){return v||1;}) == '{"a":1}');
7
8        /*=====
9        return {
10                // summary:
11                //              Functions to parse and serialize JSON
12
13                parse: function(str, strict){
14                        // summary:
15                        //              Parses a [JSON](http://json.org) string to return a JavaScript object.
16                        // description:
17                        //              This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
18                        //              Throws for invalid JSON strings. This delegates to eval() if native JSON
19                        //              support is not available. By default this will evaluate any valid JS expression.
20                        //              With the strict parameter set to true, the parser will ensure that only
21                        //              valid JSON strings are parsed (otherwise throwing an error). Without the strict
22                        //              parameter, the content passed to this method must come
23                        //              from a trusted source.
24                        // str:
25                        //              a string literal of a JSON item, for instance:
26                        //              `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
27                        // strict:
28                        //              When set to true, this will ensure that only valid, secure JSON is ever parsed.
29                        //              Make sure this is set to true for untrusted content. Note that on browsers/engines
30                        //              without native JSON support, setting this to true will run slower.
31                },
32                stringify: function(value, replacer, spacer){
33                        // summary:
34                        //              Returns a [JSON](http://json.org) serialization of an object.
35                        // description:
36                        //              Returns a [JSON](http://json.org) serialization of an object.
37                        //              This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
38                        //              Note that this doesn't check for infinite recursion, so don't do that!
39                        // value:
40                        //              A value to be serialized.
41                        // replacer:
42                        //              A replacer function that is called for each value and can return a replacement
43                        // spacer:
44                        //              A spacer string to be used for pretty printing of JSON
45                        // example:
46                        //              simple serialization of a trivial object
47                        //      |       define(["dojo/json"], function(JSON){
48                        //      |               var jsonStr = JSON.stringify({ howdy: "stranger!", isStrange: true });
49                        //      |               doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
50                }
51        };
52        =====*/
53
54        if(has("json-stringify")){
55                return JSON;
56        }else{
57                var escapeString = function(/*String*/str){
58                        // summary:
59                        //              Adds escape sequences for non-visual characters, double quote and
60                        //              backslash and surrounds with double quotes to form a valid string
61                        //              literal.
62                        return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
63                                replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
64                                replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
65                };
66                return {
67                        parse: has("json-parse") ? JSON.parse : function(str, strict){
68                                if(strict && !/^([\s\[\{]*(?:"(?:\\.|[^"])*"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){
69                                        throw new SyntaxError("Invalid characters in JSON");
70                                }
71                                return eval('(' + str + ')');
72                        },
73                        stringify: function(value, replacer, spacer){
74                                var undef;
75                                if(typeof replacer == "string"){
76                                        spacer = replacer;
77                                        replacer = null;
78                                }
79                                function stringify(it, indent, key){
80                                        if(replacer){
81                                                it = replacer(key, it);
82                                        }
83                                        var val, objtype = typeof it;
84                                        if(objtype == "number"){
85                                                return isFinite(it) ? it + "" : "null";
86                                        }
87                                        if(objtype == "boolean"){
88                                                return it + "";
89                                        }
90                                        if(it === null){
91                                                return "null";
92                                        }
93                                        if(typeof it == "string"){
94                                                return escapeString(it);
95                                        }
96                                        if(objtype == "function" || objtype == "undefined"){
97                                                return undef; // undefined
98                                        }
99                                        // short-circuit for objects that support "json" serialization
100                                        // if they return "self" then just pass-through...
101                                        if(typeof it.toJSON == "function"){
102                                                return stringify(it.toJSON(key), indent, key);
103                                        }
104                                        if(it instanceof Date){
105                                                return '"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z"'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){
106                                                        var num = it["getUTC" + prop]() + (plus ? 1 : 0);
107                                                        return num < 10 ? "0" + num : num;
108                                                });
109                                        }
110                                        if(it.valueOf() !== it){
111                                                // primitive wrapper, try again unwrapped:
112                                                return stringify(it.valueOf(), indent, key);
113                                        }
114                                        var nextIndent= spacer ? (indent + spacer) : "";
115                                        /* we used to test for DOM nodes and throw, but FF serializes them as {}, so cross-browser consistency is probably not efficiently attainable */
116                               
117                                        var sep = spacer ? " " : "";
118                                        var newLine = spacer ? "\n" : "";
119                               
120                                        // array
121                                        if(it instanceof Array){
122                                                var itl = it.length, res = [];
123                                                for(key = 0; key < itl; key++){
124                                                        var obj = it[key];
125                                                        val = stringify(obj, nextIndent, key);
126                                                        if(typeof val != "string"){
127                                                                val = "null";
128                                                        }
129                                                        res.push(newLine + nextIndent + val);
130                                                }
131                                                return "[" + res.join(",") + newLine + indent + "]";
132                                        }
133                                        // generic object code path
134                                        var output = [];
135                                        for(key in it){
136                                                var keyStr;
137                                                if(it.hasOwnProperty(key)){
138                                                        if(typeof key == "number"){
139                                                                keyStr = '"' + key + '"';
140                                                        }else if(typeof key == "string"){
141                                                                keyStr = escapeString(key);
142                                                        }else{
143                                                                // skip non-string or number keys
144                                                                continue;
145                                                        }
146                                                        val = stringify(it[key], nextIndent, key);
147                                                        if(typeof val != "string"){
148                                                                // skip non-serializable values
149                                                                continue;
150                                                        }
151                                                        // At this point, the most non-IE browsers don't get in this branch
152                                                        // (they have native JSON), so push is definitely the way to
153                                                        output.push(newLine + nextIndent + keyStr + ":" + sep + val);
154                                                }
155                                        }
156                                        return "{" + output.join(",") + newLine + indent + "}"; // String
157                                }
158                                return stringify(value, "", "");
159                        }
160                };
161        }
162});
Note: See TracBrowser for help on using the repository browser.