json.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojo._base.json"] = true;
  8. dojo.provide("dojo._base.json");
  9. dojo.fromJson = function(/*String*/ json){
  10. // summary:
  11. // Parses a [JSON](http://json.org) string to return a JavaScript object.
  12. // description:
  13. // Throws for invalid JSON strings, but it does not use a strict JSON parser. It
  14. // delegates to eval(). The content passed to this method must therefore come
  15. // from a trusted source.
  16. // json:
  17. // a string literal of a JSON item, for instance:
  18. // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
  19. return eval("(" + json + ")"); // Object
  20. };
  21. dojo._escapeString = function(/*String*/str){
  22. //summary:
  23. // Adds escape sequences for non-visual characters, double quote and
  24. // backslash and surrounds with double quotes to form a valid string
  25. // literal.
  26. return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
  27. replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
  28. replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
  29. };
  30. dojo.toJsonIndentStr = "\t";
  31. dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
  32. // summary:
  33. // Returns a [JSON](http://json.org) serialization of an object.
  34. // description:
  35. // Returns a [JSON](http://json.org) serialization of an object.
  36. // Note that this doesn't check for infinite recursion, so don't do that!
  37. // it:
  38. // an object to be serialized. Objects may define their own
  39. // serialization via a special "__json__" or "json" function
  40. // property. If a specialized serializer has been defined, it will
  41. // be used as a fallback.
  42. // prettyPrint:
  43. // if true, we indent objects and arrays to make the output prettier.
  44. // The variable `dojo.toJsonIndentStr` is used as the indent string --
  45. // to use something other than the default (tab), change that variable
  46. // before calling dojo.toJson().
  47. // _indentStr:
  48. // private variable for recursive calls when pretty printing, do not use.
  49. // example:
  50. // simple serialization of a trivial object
  51. // | var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
  52. // | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
  53. // example:
  54. // a custom serializer for an objects of a particular class:
  55. // | dojo.declare("Furby", null, {
  56. // | furbies: "are strange",
  57. // | furbyCount: 10,
  58. // | __json__: function(){
  59. // | },
  60. // | });
  61. if(it === undefined){
  62. return "undefined";
  63. }
  64. var objtype = typeof it;
  65. if(objtype == "number" || objtype == "boolean"){
  66. return it + "";
  67. }
  68. if(it === null){
  69. return "null";
  70. }
  71. if(dojo.isString(it)){
  72. return dojo._escapeString(it);
  73. }
  74. // recurse
  75. var recurse = arguments.callee;
  76. // short-circuit for objects that support "json" serialization
  77. // if they return "self" then just pass-through...
  78. var newObj;
  79. _indentStr = _indentStr || "";
  80. var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
  81. var tf = it.__json__||it.json;
  82. if(dojo.isFunction(tf)){
  83. newObj = tf.call(it);
  84. if(it !== newObj){
  85. return recurse(newObj, prettyPrint, nextIndent);
  86. }
  87. }
  88. if(it.nodeType && it.cloneNode){ // isNode
  89. // we can't seriailize DOM nodes as regular objects because they have cycles
  90. // DOM nodes could be serialized with something like outerHTML, but
  91. // that can be provided by users in the form of .json or .__json__ function.
  92. throw new Error("Can't serialize DOM nodes");
  93. }
  94. var sep = prettyPrint ? " " : "";
  95. var newLine = prettyPrint ? "\n" : "";
  96. // array
  97. if(dojo.isArray(it)){
  98. var res = dojo.map(it, function(obj){
  99. var val = recurse(obj, prettyPrint, nextIndent);
  100. if(typeof val != "string"){
  101. val = "undefined";
  102. }
  103. return newLine + nextIndent + val;
  104. });
  105. return "[" + res.join("," + sep) + newLine + _indentStr + "]";
  106. }
  107. /*
  108. // look in the registry
  109. try {
  110. window.o = it;
  111. newObj = dojo.json.jsonRegistry.match(it);
  112. return recurse(newObj, prettyPrint, nextIndent);
  113. }catch(e){
  114. // console.log(e);
  115. }
  116. // it's a function with no adapter, skip it
  117. */
  118. if(objtype == "function"){
  119. return null; // null
  120. }
  121. // generic object code path
  122. var output = [], key;
  123. for(key in it){
  124. var keyStr, val;
  125. if(typeof key == "number"){
  126. keyStr = '"' + key + '"';
  127. }else if(typeof key == "string"){
  128. keyStr = dojo._escapeString(key);
  129. }else{
  130. // skip non-string or number keys
  131. continue;
  132. }
  133. val = recurse(it[key], prettyPrint, nextIndent);
  134. if(typeof val != "string"){
  135. // skip non-serializable values
  136. continue;
  137. }
  138. // FIXME: use += on Moz!!
  139. // MOW NOTE: using += is a pain because you have to account for the dangling comma...
  140. output.push(newLine + nextIndent + keyStr + ":" + sep + val);
  141. }
  142. return "{" + output.join("," + sep) + newLine + _indentStr + "}"; // String
  143. };
  144. }