| 6 | | dojo.json = { |
| 7 | | // jsonRegistry: AdapterRegistry a registry of type-based serializers |
| 8 | | jsonRegistry: new dojo.AdapterRegistry(), |
| | 3 | dojo.fromJson = function(/*String*/ json){ |
| | 4 | // summary: |
| | 5 | // evaluates the passed string-form of a JSON object |
| | 6 | // json: |
| | 7 | // a string literal of a JSON item, for instance: |
| | 8 | // '{ "foo": [ "bar", 1, { "baz": "thud" } ] }' |
| | 9 | // return: |
| | 10 | // the result of the evaluation |
| 10 | | register: function( /*String*/ name, |
| 11 | | /*function*/ check, |
| 12 | | /*function*/ wrap, |
| 13 | | /*optional, boolean*/ override){ |
| 14 | | // summary: |
| 15 | | // Register a JSON serialization function. JSON serialization |
| 16 | | // functions should take one argument and return an object |
| 17 | | // suitable for JSON serialization: |
| 18 | | // - string |
| 19 | | // - number |
| 20 | | // - boolean |
| 21 | | // - undefined |
| 22 | | // - object |
| 23 | | // - null |
| 24 | | // - Array-like (length property that is a number) |
| 25 | | // - Objects with a "json" method will have this method called |
| 26 | | // - Any other object will be used as {key:value, ...} pairs |
| 27 | | // |
| 28 | | // If override is given, it is used as the highest priority JSON |
| 29 | | // serialization, otherwise it will be used as the lowest. |
| 30 | | // name: |
| 31 | | // a descriptive type for this serializer |
| 32 | | // check: |
| 33 | | // a unary function that will be passed an object to determine |
| 34 | | // whether or not wrap will be used to serialize the object |
| 35 | | // wrap: |
| 36 | | // the serialization function |
| 37 | | // override: |
| 38 | | // optional, determines if the this serialization function will be |
| 39 | | // given priority in the test order |
| | 12 | // FIXME: should this accept mozilla's optional second arg? |
| | 13 | try { |
| | 14 | return eval("(" + json + ")"); |
| | 15 | }catch(e){ |
| | 16 | console.debug(e); |
| | 17 | return json; |
| | 18 | } |
| | 19 | } |
| 41 | | dojo.json.jsonRegistry.register(name, check, wrap, override); |
| 42 | | }, |
| | 21 | dojo.toJson = function(/*Object*/ o){ |
| | 22 | // summary: |
| | 23 | // Create a JSON serialization of an object, note that this |
| | 24 | // doesn't check for infinite recursion, so don't do that! |
| | 25 | // o: |
| | 26 | // an object to be serialized. Objects may define their own |
| | 27 | // serialization via a special "__json__" or "json" function |
| | 28 | // property. If a specialized serializer has been defined, it will |
| | 29 | // be used as a fallback. |
| | 30 | // return: |
| | 31 | // a String representing the serialized version of the passed |
| | 32 | // object |
| 44 | | evalJson: function(/*String*/ json){ |
| 45 | | // summary: |
| 46 | | // evaluates the passed string-form of a JSON object |
| 47 | | // json: |
| 48 | | // a string literal of a JSON item, for instance: |
| 49 | | // '{ "foo": [ "bar", 1, { "baz": "thud" } ] }' |
| 50 | | // return: |
| 51 | | // the result of the evaluation |
| 52 | | |
| 53 | | // FIXME: should this accept mozilla's optional second arg? |
| 54 | | try { |
| 55 | | return eval("(" + json + ")"); |
| 56 | | }catch(e){ |
| 57 | | dojo.debug(e); |
| 58 | | return json; |
| | 34 | var objtype = typeof(o); |
| | 35 | if(objtype == "undefined"){ |
| | 36 | return "undefined"; |
| | 37 | }else if((objtype == "number")||(objtype == "boolean")){ |
| | 38 | return o + ""; |
| | 39 | }else if(o === null){ |
| | 40 | return "null"; |
| | 41 | } |
| | 42 | if (objtype == "string") { return dojo.string.escapeString(o); } |
| | 43 | // recurse |
| | 44 | var me = arguments.callee; |
| | 45 | // short-circuit for objects that support "json" serialization |
| | 46 | // if they return "self" then just pass-through... |
| | 47 | var newObj; |
| | 48 | if(typeof(o.__json__) == "function"){ |
| | 49 | newObj = o.__json__(); |
| | 50 | if(o !== newObj){ |
| | 51 | return me(newObj); |
| 60 | | }, |
| 61 | | |
| 62 | | serialize: function(/*Object*/ o){ |
| 63 | | // summary: |
| 64 | | // Create a JSON serialization of an object, note that this |
| 65 | | // doesn't check for infinite recursion, so don't do that! |
| 66 | | // o: |
| 67 | | // an object to be serialized. Objects may define their own |
| 68 | | // serialization via a special "__json__" or "json" function |
| 69 | | // property. If a specialized serializer has been defined, it will |
| 70 | | // be used as a fallback. |
| 71 | | // return: |
| 72 | | // a String representing the serialized version of the passed |
| 73 | | // object |
| 74 | | |
| 75 | | var objtype = typeof(o); |
| 76 | | if(objtype == "undefined"){ |
| 77 | | return "undefined"; |
| 78 | | }else if((objtype == "number")||(objtype == "boolean")){ |
| 79 | | return o + ""; |
| 80 | | }else if(o === null){ |
| 81 | | return "null"; |
| | 53 | } |
| | 54 | if(typeof(o.json) == "function"){ |
| | 55 | newObj = o.json(); |
| | 56 | if (o !== newObj) { |
| | 57 | return me(newObj); |
| 95 | | if(typeof(o.json) == "function"){ |
| 96 | | newObj = o.json(); |
| 97 | | if (o !== newObj) { |
| 98 | | return me(newObj); |
| 99 | | } |
| | 70 | return "[" + res.join(",") + "]"; |
| | 71 | } |
| | 72 | // look in the registry |
| | 73 | /* |
| | 74 | try { |
| | 75 | window.o = o; |
| | 76 | newObj = dojo.json.jsonRegistry.match(o); |
| | 77 | return me(newObj); |
| | 78 | }catch(e){ |
| | 79 | // console.debug(e); |
| | 80 | } |
| | 81 | // it's a function with no adapter, bad |
| | 82 | */ |
| | 83 | if(objtype == "function"){ |
| | 84 | return null; |
| | 85 | } |
| | 86 | // generic object code path |
| | 87 | res = []; |
| | 88 | for (var k in o){ |
| | 89 | var useKey; |
| | 90 | if (typeof(k) == "number"){ |
| | 91 | useKey = '"' + k + '"'; |
| | 92 | }else if (typeof(k) == "string"){ |
| | 93 | useKey = dojo.string.escapeString(k); |
| | 94 | }else{ |
| | 95 | // skip non-string or number keys |
| | 96 | continue; |
| 113 | | // look in the registry |
| 114 | | try { |
| 115 | | window.o = o; |
| 116 | | newObj = dojo.json.jsonRegistry.match(o); |
| 117 | | return me(newObj); |
| 118 | | }catch(e){ |
| 119 | | // dojo.debug(e); |
| 120 | | } |
| 121 | | // it's a function with no adapter, bad |
| 122 | | if(objtype == "function"){ |
| 123 | | return null; |
| 124 | | } |
| 125 | | // generic object code path |
| 126 | | res = []; |
| 127 | | for (var k in o){ |
| 128 | | var useKey; |
| 129 | | if (typeof(k) == "number"){ |
| 130 | | useKey = '"' + k + '"'; |
| 131 | | }else if (typeof(k) == "string"){ |
| 132 | | useKey = dojo.string.escapeString(k); |
| 133 | | }else{ |
| 134 | | // skip non-string or number keys |
| 135 | | continue; |
| 136 | | } |
| 137 | | val = me(o[k]); |
| 138 | | if(typeof(val) != "string"){ |
| 139 | | // skip non-serializable values |
| 140 | | continue; |
| 141 | | } |
| 142 | | res.push(useKey + ":" + val); |
| 143 | | } |
| 144 | | return "{" + res.join(",") + "}"; |
| | 103 | res.push(useKey + ":" + val); |