JavaScript数据格式/漂亮的打印机
我试图find一种方法来pretty print
JavaScript数据结构以可读的forms进行debugging。
我有一个相当大而复杂的数据结构存储在JS中,我需要编写一些代码来操纵它。 为了弄清楚我在做什么以及在哪里出错,我真正需要的是能够看到整个数据结构,并且在我通过UI进行更改时进行更新。
所有这些东西,我可以处理自己,除了find一个很好的方法来将JavaScript数据结构转储为可读的string。 JSON会做,但它确实需要很好地格式化和缩进。 我通常使用Firebug的优秀的DOM倾销的东西,但我真的需要能够看到整个结构,这似乎不可能在Firebug。
任何build议,欢迎。
提前致谢。
我写了一个函数来转储一个JS对象的可读格式,虽然输出没有缩进,但不应该太难添加:我做了一个我为Lua制作的函数(这更复杂)处理这个缩进问题。
这里是“简单”版本:
function DumpObject(obj) { var od = new Object; var result = ""; var len = 0; for (var property in obj) { var value = obj[property]; if (typeof value == 'string') value = "'" + value + "'"; else if (typeof value == 'object') { if (value instanceof Array) { value = "[ " + value + " ]"; } else { var ood = DumpObject(value); value = "{ " + ood.dump + " }"; } } result += "'" + property + "' : " + value + ", "; len++; } od.dump = result.replace(/, $/, ""); od.len = len; return od; }
我会考虑改进一下。
注1:要使用它,请执行od = DumpObject(something)
并使用od.dump。 抱怨,因为我也想要len值(项目数)为另一个目的。 使函数仅返回string是微不足道的。
注2:它不处理引用中的循环。
编辑
我做了缩进的版本。
function DumpObjectIndented(obj, indent) { var result = ""; if (indent == null) indent = ""; for (var property in obj) { var value = obj[property]; if (typeof value == 'string') value = "'" + value + "'"; else if (typeof value == 'object') { if (value instanceof Array) { // Just let JS convert the Array to a string! value = "[ " + value + " ]"; } else { // Recursive dump // (replace " " by "\t" or something else if you prefer) var od = DumpObjectIndented(value, indent + " "); // If you like { on the same line as the key //value = "{\n" + od + "\n" + indent + "}"; // If you prefer { and } to be aligned value = "\n" + indent + "{\n" + od + "\n" + indent + "}"; } } result += indent + "'" + property + "' : " + value + ",\n"; } return result.replace(/,\n$/, ""); }
在recursion调用的行上select你的缩进,通过在这个之后切换注释行来支持样式。
…我看到你掀起了自己的版本,这是很好的。 游客将有一个select。
像这样使用Crockford的JSON.stringify :
var myArray = ['e', {pluribus: 'unum'}]; var text = JSON.stringify(myArray, null, '\t'); //you can specify a number instead of '\t' and that many spaces will be used for indentation...
variablestext
将如下所示:
[ "e", { "pluribus": "unum" } ]
顺便说一句,这只需要那个JS文件 – 它将适用于任何库等。
在Firebug
,如果你只是console.debug ("%o", my_object)
你可以在控制台上点击它并input一个交互式对象浏览器。 它显示整个对象,并让您展开嵌套的对象。
您可以使用以下内容
<pre id="dump"></pre> <script> var dump = JSON.stringify(sampleJsonObject, null, 4); $('#dump').html(dump) </script>
对于那些寻找一个真棒的方式来看你的对象, 检查prettyPrint.js
创build一个带有可configuration视图选项的表格,将其打印在文档的某处。 比在console
更好看。
var tbl = prettyPrint( myObject, { /* options such as maxDepth, etc. */ }); document.body.appendChild(tbl);
我在Rhino
编程,我不满意任何在这里发布的答案。 所以我写了自己漂亮的打印机:
function pp(object, depth, embedded) { typeof(depth) == "number" || (depth = 0) typeof(embedded) == "boolean" || (embedded = false) var newline = false var spacer = function(depth) { var spaces = ""; for (var i=0;i<depth;i++) { spaces += " "}; return spaces } var pretty = "" if ( typeof(object) == "undefined" ) { pretty += "undefined" } else if ( typeof(object) == "boolean" || typeof(object) == "number" ) { pretty += object.toString() } else if ( typeof(object) == "string" ) { pretty += "\"" + object + "\"" } else if ( object == null) { pretty += "null" } else if ( object instanceof(Array) ) { if ( object.length > 0 ) { if (embedded) { newline = true } var content = "" for each (var item in object) { content += pp(item, depth+1) + ",\n" + spacer(depth+1) } content = content.replace(/,\n\s*$/, "").replace(/^\s*/,"") pretty += "[ " + content + "\n" + spacer(depth) + "]" } else { pretty += "[]" } } else if (typeof(object) == "object") { if ( Object.keys(object).length > 0 ){ if (embedded) { newline = true } var content = "" for (var key in object) { content += spacer(depth + 1) + key.toString() + ": " + pp(object[key], depth+2, true) + ",\n" } content = content.replace(/,\n\s*$/, "").replace(/^\s*/,"") pretty += "{ " + content + "\n" + spacer(depth) + "}" } else { pretty += "{}"} } else { pretty += object.toString() } return ((newline ? "\n" + spacer(depth) : "") + pretty) }
输出如下所示:
js> pp({foo:"bar", baz: 1}) { foo: "bar", baz: 1 } js> var taco js> pp({foo:"bar", baz: [1,"taco",{"blarg": "moo", "mine": "craft"}, null, taco, {}], bleep: {a:null, b:taco, c: []}}) { foo: "bar", baz: [ 1, "taco", { blarg: "moo", mine: "craft" }, null, undefined, {} ], bleep: { a: null, b: undefined, c: [] } }
我也已经把它作为一个Gist发布在这里,以便将来可能会有所改变。
对于Node.js,使用:
util.inspect(object, [options]);
API文档
jsDump
jsDump.parse([ window, document, { a : 5, '1' : 'foo' }, /^[ab]+$/g, new RegExp('x(.*?)z','ig'), alert, function fn( x, y, z ){ return x + y; }, true, undefined, null, new Date(), document.body, document.getElementById('links') ])
变
[ [Window], [Document], { "1": "foo", "a": 5 }, /^[ab]+$/g, /x(.*?)z/gi, function alert( a ){ [code] }, function fn( a, b, c ){ [code] }, true, undefined, null, "Fri Feb 19 2010 00:49:45 GMT+0300 (MSK)", <body id="body" class="node"></body>, <div id="links"> ]
QUnit (由jQuery使用的unit testing框架)使用略微修补的jsDump版本。
JSON.stringify()在某些情况下不是最好的select。
JSON.stringify({f:function(){}}) // "{}" JSON.stringify(document.body) // TypeError: Converting circular structure to JSON
以PhiLho的领导(非常感谢:)),我最终写了我自己的,因为我不能让他做我想做的事情。 这是相当粗糙和准备,但它做我需要的工作。 谢谢大家的优秀build议。
我知道,这不是一个好的代码,而是它的价值所在。 有人可能会觉得它有用:
// Usage: dump(object) function dump(object, pad){ var indent = '\t' if (!pad) pad = '' var out = '' if (object.constructor == Array){ out += '[\n' for (var i=0; i<object.length; i++){ out += pad + indent + dump(object[i], pad + indent) + '\n' } out += pad + ']' }else if (object.constructor == Object){ out += '{\n' for (var i in object){ out += pad + indent + i + ': ' + dump(object[i], pad + indent) + '\n' } out += pad + '}' }else{ out += object } return out }
这实际上只是对Jason Bunting的“使用Crockford的JSON.stringify”发表评论,但我无法对该答案添加评论。
正如评论中指出的那样,JSON.stringify在Prototype(www.prototypejs.org)库中运行得不好。 但是,通过临时删除原型添加的Array.prototype.toJSON方法,运行Crockford的stringify(),然后将其放回原样,可以很容易地使它们在一起玩:
var temp = Array.prototype.toJSON; delete Array.prototype.toJSON; $('result').value += JSON.stringify(profile_base, null, 2); Array.prototype.toJSON = temp;
我认为J. Buntings使用JSON.stringify的回应也很好。 另外,如果你正在使用YUI,你可以通过YUI的JSON对象使用JSON.stringify。 在我的情况下,我需要转储到HTML,所以更容易调整/剪切/粘贴PhiLho响应。
function dumpObject(obj, indent) { var CR = "<br />", SPC = " ", result = ""; if (indent == null) indent = ""; for (var property in obj) { var value = obj[property]; if (typeof value == 'string') { value = "'" + value + "'"; } else if (typeof value == 'object') { if (value instanceof Array) { // Just let JS convert the Array to a string! value = "[ " + value + " ]"; } else { var od = dumpObject(value, indent + SPC); value = CR + indent + "{" + CR + od + CR + indent + "}"; } } result += indent + "'" + property + "' : " + value + "," + CR; } return result; }
许多人在这个线程中编写代码,对各种陷阱有很多评论。 我喜欢这个解决scheme,因为它看起来很完整,并且是一个没有依赖关系的文件。
浏览器
的NodeJS
它“开箱即用”,并有节点和浏览器版本(大概只是不同的包装,但我没有挖掘确认)。
该库还支持漂亮的打印XML,SQL和CSS,但我没有尝试过这些function。
一个简单的打印作为string的元素:
var s = ""; var len = array.length; var lenMinus1 = len - 1 for (var i = 0; i < len; i++) { s += array[i]; if(i < lenMinus1) { s += ", "; } } alert(s);
我的NeatJSON库有Ruby和JavaScript版本 。 它根据(许可)MIT许可证免费提供。 您可以在以下url查看在线演示/转换器:
http://phrogz.net/JS/neatjson/neatjson.html
一些function(全部可选):
- 裹到一个特定的宽度; 如果一个对象或数组可以放在线上,它将保持在一行上。
- alignment对象中所有键的冒号。
- 按字母顺序将键sorting。
- 将浮点数格式化为特定的小数位数。
- 在包装时,使用一个'short'版本,将数组和对象的开放/closures括号放在第一个/最后一个值的同一行上。
- 以细粒度的方式控制数组和对象的空白(在括号内,在冒号和逗号之前/之后)。
- 在Web浏览器中工作,并作为Node.js模块工作。
flexjson包含一个prettyPrint()函数,可能会给你你想要的。