JavaScriptデータフォーマット/プリティプリンター


124

pretty print人間が読める形式のJavaScriptデータ構造をデバッグする方法を見つけようとしています。

JSに格納されているかなり大きくて複雑なデータ構造があり、それを操作するためのコードを記述する必要があります。私が何をしていてどこが間違っているのかを理解するために本当に必要なのは、データ構造全体を確認し、UIを介して変更を加えるたびに更新できるようにすることです。

JavaScriptデータ構造を人間が読める形式の文字列にダンプする良い方法を見つけることを除いて、私が自分で処理できるすべてのもの。JSONでも大丈夫ですが、実際には適切にフォーマットしてインデントする必要があります。通常は、Firebugの優れたDOMダンピング機能を使用しますが、構造全体を一度に表示できるようにする必要がありますが、Firebugでは不可能と思われます。

どんな提案も大歓迎です。

前もって感謝します。


回答の編集が通知されるかどうかはわかりません。そこで、このコメントを書いて、インデントされたダンプの独自バージョンを追加したことをお知らせします。:-)
PhiLho 2008

注:JSON.stringify()の回答は非常に役立つようですが、「the」の回答としては受け入れられません。
GuruM 2013

nodedumpを使用して、オブジェクトの視覚的で直感的な出力を得ることができます:github.com/ragamufin/nodedump
ragamufin

そこを見てみましょう:stackoverflow.com/questions/4810841/...
monkeythedev

回答:


31

出力はインデントされていませんが、JSオブジェクトを読み取り可能な形式でダンプする関数を作成しましたが、それを追加するのはそれほど難しくないはずです。 )このインデントの問題を処理しました。

これが「シンプル」バージョンです。

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$/, "");
}

再帰呼び出しの行でインデントを選択し、コメント行をこの行の後に切り替えることでスタイルを固定できます。

...自分のバージョンをホイップアップしたようです。これは良いことです。訪問者には選択肢があります。


1
私は好きです;)それを適切に機能させることはできませんが、よろしければ、私は恥ずかしげもなくコンセプトを盗み、自分で書きます:)
Dan

2
このアプローチの欠点の1つは(Jasonが提案するJSON.stringifyメソッドと比較して)、オブジェクトの配列が適切に表示されないことです。オブジェクトの配列がある場合、[object Object]として表示されます。
ライアン

@ライアン:ブラウザーのネイティブオブジェクトですか?はい、コードを振り返ると、コメントが追加されているのがわかりました。より堅牢なものが必要な場合は、以下の代替案があると思います。
PhiLho

これは使えません。jsonデータをダンプしようとすると、無限ループが発生します。
neoneye

1
@RaphaelDDL&PhiLho-小さなオブジェクトで最大呼び出しスタックサイズをトリガーすることもできます。自分自身へのプロパティ参照を持つもの。そのような参照は、この関数で無限ループを引き起こします。
skibulk 2013

233

次のように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ファイルだけが必要です。ライブラリなどで動作します。


5
これはほぼ間違いなく、あなたが得ようとしている最良の答えです。私は4人または5人の非プログラマーに、JSON.stringifiedデータ構造を読み取って編集し、それらを構成ファイルに幅広く使用することを教えました。
Joel Anair 2008

1
それが問題を引き起こすのは奇妙です-それはあなたに問題を引き起こすかもしれないので、グローバル名前空間に「JSON」という名前を導入します。これを追加する前にネームスペースで「JSON」を確認し、衝突が存在するかどうかを確認してください。
Jason Bunting

1
まあ、プロトタイプはそのような悪です...;)
ジェイソン・バンティング

7
Firefox 3.5以降では、JSON.stringifyが組み込まれています。(developer.mozilla.org/En/Using_JSON_in_Firefox)なので、デバッグ目的でJSONオブジェクトを表示するだけの場合は、追加のJS依存関係なしで実行できます。
Greg Bernhardt、

3
Chromeでも。ただし、JSON.stringifyは循環データJSON.stringify((function(){var x = []; x.push(x); return x})())や他の多くの種類のオブジェクトでは失敗しますJSON.stringify(/foo/)
Kragen Javier Sitaker、2011年

21

以下を使用できます

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

15

ではFirebugconsole.debug ("%o", my_object)コンソールでそれをクリックするだけで、インタラクティブなオブジェクトエクスプローラーに入ることができます。オブジェクト全体が表示され、ネストされたオブジェクトを展開できます。


1
問題は、「最上位」のオブジェクトのみを表示することです。何十ものネストされたオブジェクトがあり、コンテンツ全体を一度に確認できる必要があります。重要なのは、どこが変化しているかを確認できることです。したがって、この場合、Firebugは実際には機能しません。
Dan

(はい、クリックして展開できることを知っていますが、データをダンプするたびに10個ほどのリンクをクリックするのが、現在私がやっていることです-進行が非常に遅い)
Dan

1
これはChromeでも機能します(したがって、おそらくSafariでも機能します)。
Kragen Javier Sitaker


9

オブジェクトを確認するための素晴らしい方法をお探しの方は、prettyPrint.jsを確認してください

ドキュメントのどこかに印刷される設定可能なビューオプションを含むテーブルを作成します。で見るよりも良いconsoleです。

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

ここに画像の説明を入力してください


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

ここに要旨として投稿しました将来の変更が必要になる可能性がある場合はに。


7
きれいなプリンターかもしれませんが、コードは実際にはとてもきれいに見えません:)
Xion

3

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少しパッチを当てたバージョンのjsDumpを使用する(jQueryで使用されるユニットテストフレームワーク)。


JSON.stringify()は、場合によっては最良の選択ではありません。

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

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
}

1
ちなみに、できますが、セミコロンなしで行を終了しないでください。また、__ if(!pad)pad = '' __の標準的な実行方法は次のようになります:__ pad =(pad || '')__
Jason Bunting

if(!foo)foo = ... vs foo =(foo || ...)についてあなたの意見を述べますが、すべての行をセミコロンで終了する根拠は何ですか?
ダン

1
そうでない場合は、言語のいくつかの厄介な特異性に遭遇します。言うまでもなく、コードを簡単に縮小することはできません(たまたま使用する縮小記号がセミコロンを挿入するのに十分な場合を除きます)。詳細については、stackoverflow.com / questions / 42247をご覧ください。
Jason Bunting

1
if(!pad)pad = ''; pad =(pad || '');よりも安価で、柔軟性が高く、読みやすくなっています。少しではありますが。そのフォームを主張する場合は、余分な括弧を削除してください。パッド=パッド|| ''; セミコロンの3つの理由:JSは、セミコロンを省略するとエラーがスローされることがわかったときに、エンド行のセミコロンを自動挿入します。1)これは、自分で追加するよりも少し遅い速度で実行されます。2)次の行が結合されたときにエラーがスローされず、エラーが発生する可能性があります。3)コードが縮小されるのを防ぎます。
SamGoody

1

これは実際にはJason Buntingの「Use Crockford's 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;

1

JSON.stringifyを使用したときのJ. Buntingsの応答も良いと思いました。余談ですが、たまたま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;
}

1

多くの人々がこのスレッドでコードを書いており、さまざまな落とし穴について多くのコメントが寄せられています。このソリューションは、完全であるように見え、依存関係のない単一のファイルであったため、気に入りました。

ブラウザ

nodejs

「そのまま」機能し、ノードとブラウザの両方のバージョンがあります(おそらく異なるラッパーだけですが、確認するために掘り出しませんでした)。

このライブラリは、XML、SQL、CSSのかなりの印刷もサポートしていますが、私はそれらの機能を試していません。


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

0

私のNeatJSONライブラリにはRuby バージョンJavaScriptバージョンの両方があります。これは(許可)MITライセンスの下で自由に利用できます。オンラインのデモ/コンバーターは、http//phrogz.net/JS/neatjson/neatjson.htmlで表示できます。

一部の機能(すべてオプション):

  • 特定の幅に折り返します。オブジェクトまたは配列が行に収まる場合は、1行に保持されます。
  • オブジェクト内のすべてのキーのコロンを揃えます。
  • オブジェクトのキーをアルファベット順に並べ替えます。
  • 浮動小数点数を特定の小数にフォーマットします。
  • ラップするときは、配列とオブジェクトの開始/終了ブラケットを最初と最後の値と同じ行に置く「短い」バージョンを使用します。
  • 配列とオブジェクトの空白を細かく制御します(括弧内、コロンとコンマの前後)。
  • Webブラウザーで、Node.jsモジュールとして機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.