代码之家  ›  专栏  ›  技术社区  ›  Dan Aditi

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

  •  120
  • Dan Aditi  · 技术社区  · 16 年前

    我在想办法 pretty print 用于调试的可读形式的javascript数据结构。

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

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

    欢迎提出任何建议。

    事先谢谢。

    15 回复  |  直到 9 年前
        1
  •  28
  •   gprathour davidbuzatto    10 年前

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

    在递归调用的行上选择缩进,并在这一行之后切换注释行,从而形成大括号样式。

    …我看到你自己编了一个版本,这很好。参观者可以选择。

        2
  •  223
  •   gprathour davidbuzatto    10 年前

    使用 Crockford's 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文件—它可以与任何库等一起使用。

        3
  •  19
  •   gprathour davidbuzatto    10 年前

    您可以使用以下内容

    <pre id="dump"></pre>
    <script>
       var dump = JSON.stringify(sampleJsonObject, null, 4); 
       $('#dump').html(dump)
    </script>
    
        4
  •  15
  •   gprathour davidbuzatto    10 年前

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

        5
  •  10
  •   gprathour davidbuzatto    10 年前

    对于node.js,使用:

    util.inspect(object, [options]);
    

    API Documentation

        6
  •  9
  •   RaphaelDDL    10 年前

    对于那些想找一个很棒的方式看你的物品的人, check prettyPrint.js

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

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

    enter image description here

        7
  •  6
  •   community wiki 2 revs, 2 users 97% knowtheory    10 年前

    我正在编程 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 here 无论将来需要做什么改变。

        8
  •  2
  •   NVI    14 年前

    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使用的单元测试框架)使用稍微打补丁的jsdump版本。


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

    JSON.stringify({f:function(){}}) // "{}"
    JSON.stringify(document.body)    // TypeError: Converting circular structure to JSON
    
        9
  •  1
  •   Dan Aditi    16 年前

    在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
    }
    
        10
  •  1
  •   Peter Rust    14 年前

    这真的只是对JasonBunting的“使用Crockford的json.Stringify”的评论,但我无法对那个答案添加评论。

    正如注释中所指出的,json.stringify不能很好地处理原型(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;
    
        11
  •  1
  •   GTM    13 年前

    我认为J.Buntings对使用json.stringify的响应也不错。另外,如果您碰巧使用了yui,那么可以通过yuis 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;
    }
    
        12
  •  1
  •   gprathour davidbuzatto    10 年前

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

    browser

    nodejs

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

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

        13
  •  0
  •   aliteralmind    10 年前

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

    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);
    
        14
  •  0
  •   Phrogz    9 年前

    我的 NeatJSON 库既有Ruby又有 JavaScript versions . 它在麻省理工学院许可证下免费提供。您可以在以下位置查看在线演示/转换器:
    http://phrogz.net/JS/neatjson/neatjson.html

    一些功能(全部可选):

    • 换行到特定的宽度;如果对象或数组可以放在一行上,则它将保持在一行上。
    • 对齐对象中所有键的冒号。
    • 按字母顺序对对象的键排序。
    • 将浮点数格式化为特定的小数位数。
    • 包装时,请使用“短”版本,将数组和对象的左/右括号与第一个/最后一个值放在同一行。
    • 以粒度方式控制数组和对象的空白(括号内、冒号前/后和逗号)。
    • 在Web浏览器和node.js模块中工作。
        15
  •  -5
  •   andy    16 年前

    flexjson 包括一个prettyprint()函数,该函数可以提供您想要的内容。