JavaScript 数据格式化/漂亮打印机

我正在试图找到一种方法来“漂亮地打印”一个 JavaScript 数据结构,以便用于调试。

我有一个相当大和复杂的数据结构存储在 JS 中,我需要编写一些代码来操作它。为了弄清楚我在做什么以及我在哪里出了错,我真正需要的是能够看到整个数据结构,并在我通过 UI 进行更改时更新它。

所有这些东西我都可以自己处理,除了找到一种很好的方法将 JavaScript 数据结构转储为人类可读的字符串。JSON 也可以,但是它确实需要很好的格式化和缩进。我通常会使用 Firebug 优秀的 DOM 转储工具,但是我真的需要能够一次看到整个结构,这在 Firebug 中似乎是不可能的。

92836 次浏览

Firebug中,如果您只是 console.debug ("%o", my_object),您可以在控制台中单击它并输入一个交互式对象资源管理器。它显示整个对象,并允许您展开嵌套对象。

Flexjson 包含一个可能提供所需内容的 pretyPrint ()函数。

像这样使用 克罗克福德的 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...

变量 text应该是这样的:

[
"e",
{
"pluribus": "unum"
}
]

顺便说一下,这只需要那个 JS 文件——它可以与任何库一起工作,等等。

我编写了一个函数来以可读的形式转储一个 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 值(项目数量)作为另一个用途。使函数只返回字符串是很简单的。
注意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$/, "");
}

在递归调用的行上选择缩进,然后通过切换注释行来支撑样式。

... 我看到你做了自己的版本,很好,访客可以选择。

由于我不能完全让他按照我的意愿去做,所以我以 PhhiLho 的领导(非常感谢:)结束了我自己的写作。虽然很粗糙,但是很适合我的工作。谢谢你们的好建议。

我知道这不是什么高明的代码,但是不管怎么说,这就是它。有人可能会发现它很有用:

// 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 的“ Use Crocford’s JSON.stringify”的一个评论,但我不能给这个答案添加评论。

正如评论中指出的那样,JSON.stringify 不能很好地使用 Prototype ( www.prototypejs.org )库。然而,通过暂时移除原型添加的 Array.Prototype.toJSON 方法,运行 Crocford 的 stringify () ,然后像下面这样放回去,很容易使它们能够很好地一起工作:

  var temp = Array.prototype.toJSON;
delete Array.prototype.toJSON;
$('result').value += JSON.stringify(profile_base, null, 2);
Array.prototype.toJSON = temp;

扔掉

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 使用的单元测试框架)使用稍作修补的 jsDump 版本。


Stringify ()在某些情况下不是最佳选择。

JSON.stringify({f:function(){}}) // "{}"
JSON.stringify(document.body)    // TypeError: Converting circular structure to JSON

我认为 J.Buntings 对使用 JSON.stringify 的反应也很好。顺便说一句,如果您正好使用 YUI,那么可以通过 YUIs JSON 对象使用 JSON.stringify。在我的例子中,我需要转储到 HTML,这样可以更容易地调整/剪切/粘贴 PhilLho 响应。

function dumpObject(obj, indent)
{
var CR = "<br />", SPC = "&nbsp;&nbsp;&nbsp;&nbsp;", 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;
}

我在用 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: []
}
}

我还将其作为 大意是发布,以备将来可能需要的任何更改。

对于 Node.js,使用:

util.inspect(object, [options]);

API 文件

您可以使用以下内容

<pre id="dump"></pre>
<script>
var dump = JSON.stringify(sampleJsonObject, null, 4);
$('#dump').html(dump)
</script>

很多人在这个线程中编写代码,其中有很多关于各种陷阱的注释。我喜欢这个解决方案,因为它看起来很完整,是一个没有依赖关系的单一文件。

浏览器

Nodejs

它的工作“开箱即用”,并有节点和浏览器版本(可能只是不同的包装,但我没有深入确认)。

该库还支持打印漂亮的 XML、 SQL 和 CSS,但我还没有尝试这些特性。

对于那些寻找一个可怕的方式来看你的对象,检查 pretty tyPrint.js

创建一个具有可配置视图选项的表,以便在文档的某个位置打印。看起来总比看 console好。

var tbl = prettyPrint( myObject, { /* options such as maxDepth, etc. */ });
document.body.appendChild(tbl);

enter image description here

将元素打印为字符串的简单方法:

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);

我的 整洁的 JSON库同时具有 Ruby 和 JavaScript 版本。它是在 MIT 许可证下免费提供的。您可以在以下网址查看在线演示/转换器:
Http://phrogz.net/js/neatjson/neatjson.html

一些特性(全部可选) :

  • 换行到一个特定的宽度; 如果一个对象或数组可以放在这条线上,它就保持在一条线上。
  • 对齐对象中所有键的冒号。
  • 按字母顺序对对象的键进行排序。
  • 将浮点数格式化为特定数目的小数。
  • 在进行换行时,使用“ short”版本,将数组和对象的开/关括号放在与第一个/最后一个值相同的行上。
  • 以粒度的方式控制数组和对象的空白(在括号内,冒号和逗号之前/之后)。
  • 可以在 web 浏览器中作为 Node.js 模块使用。

对于任何在2021年或2021年后查看这个问题的人来说

看看这个其他 StackOverflow 的回答哈桑

TLDR:

JSON.stringify(data,null,2)

这里的第三个参数是 tab/space