127

我试图找到一种方法以人类可读的形式“漂亮地打印”JavaScript 数据结构以进行调试。

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

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

4

16 回答 16

238

像这样使用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...

变量text看起来像这样:

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

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

于 2008-09-24T23:01:01.387 回答
33

我写了一个函数来以可读的形式转储一个 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$/, "");
}

在递归调用的行上选择您的缩进,并通过在此之后切换注释行来支持样式。

...我看到您制作了自己的版本,这很好。游客将有一个选择。

于 2008-09-24T23:06:46.350 回答
21

您可以使用以下

<pre id="dump"></pre>
<script>
   var dump = JSON.stringify(sampleJsonObject, null, 4); 
   $('#dump').html(dump)
</script>
于 2012-07-23T05:42:35.123 回答
15

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

于 2008-09-24T22:48:56.660 回答
12

对于 Node.js,使用:

util.inspect(object, [options]);

API 文档

于 2011-10-05T18:55:56.683 回答
9

对于那些正在寻找一种很棒的方式来查看您的对象的人,请查看 prettyPrint.js

创建一个带有可配置视图选项的表格,以打印在文档的某处。看起来比在console.

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

在此处输入图像描述

于 2013-06-21T13:12:05.920 回答
6

我正在编程,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 发布在这里。

于 2011-04-11T05:53:01.537 回答
3

js转储

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 的略微修补版本。


JSON.stringify() 在某些情况下不是最佳选择。

JSON.stringify({f:function(){}}) // "{}"
JSON.stringify(document.body)    // TypeError: Converting circular structure to JSON
于 2010-02-18T22:00:59.473 回答
2

在 PhiLho 的带领下(非常感谢 :)),我最终写了自己的,因为我无法让他做我想做的事。它非常粗糙且准备就绪,但它完成了我需要的工作。谢谢大家的出色建议。

我知道,这不是出色的代码,但就其价值而言,就在这里。有人可能会觉得它很有用:

// 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
}
于 2008-09-24T23:37:38.367 回答
1

这实际上只是对 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;
于 2010-02-18T21:46:56.380 回答
1

我认为 J. Buntings 对使用 JSON.stringify 的反应也很好。顺便说一句,如果你碰巧在使用 YUI,你可以通过 YUI 的 JSON 对象使用 JSON.stringify。在我的情况下,我需要转储到 HTML,以便调整/剪切/粘贴 PhiLho 响应更容易。

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;
}
于 2011-03-29T16:24:57.180 回答
1

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

浏览器

节点

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

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

于 2013-03-21T16:00:52.980 回答
1

对于在 2021 年或 2021 年后检查此问题的任何人

查看hassan的其他 StackOverflow 答案

TLDR:

JSON.stringify(data,null,2)

这里第三个参数是制表符/空格

于 2021-02-12T09:54:12.307 回答
0

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

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);
于 2014-08-29T18:29:06.520 回答
0

我的NeatJSON库有 Ruby 和JavaScript 版本。它在(许可的)MIT 许可下免费提供。您可以在以下位置查看在线演示/转换器: http:
//phrogz.net/JS/neatjson/neatjson.html

一些功能(全部可选):

  • 包裹到特定宽度;如果一个对象或数组可以放在一行上,它就保持在一行上。
  • 对齐对象中所有键的冒号。
  • 按字母顺序对对象的键进行排序。
  • 将浮点数格式化为特定的小数位数。
  • 换行时,使用“短”版本,将数组和对象的开/关括号与第一个/最后一个值放在同一行。
  • 以精细的方式控制数组和对象的空白(在括号内、冒号和逗号之前/之后)。
  • 在 Web 浏览器中工作并作为 Node.js 模块工作。
于 2015-04-20T16:17:28.497 回答
-5

flexjson包含一个 prettyPrint() 函数,它可能会给你想要的东西。

于 2008-09-24T22:50:52.457 回答