JavaScript veri biçimlendirme / güzel yazıcı


124

pretty printHata ayıklama için insan tarafından okunabilir bir biçimde JavaScript veri yapısının bir yolunu bulmaya çalışıyorum .

JS'de depolanan oldukça büyük ve karmaşık bir veri yapım var ve onu işlemek için biraz kod yazmam gerekiyor. Ne yaptığımı ve nerede yanlış gittiğimi anlamak için gerçekten ihtiyacım olan şey, veri yapısını bütünüyle görebilmek ve kullanıcı arayüzü aracılığıyla her değişiklik yaptığımda onu güncelleyebilmek.

JavaScript veri yapısını insan tarafından okunabilir bir dizeye dökmenin güzel bir yolunu bulmanın dışında, tüm bunları kendim halledebilirim. JSON yapardı, ancak gerçekten güzel bir şekilde biçimlendirilmesi ve girintilendirilmesi gerekiyor. Bunun için genellikle Firebug'ın mükemmel DOM dökümünü kullanırdım, ancak gerçekten tüm yapıyı aynı anda görebilmem gerekiyor, ki bu Firebug'da mümkün görünmüyor.

Herhangi bir öneriye açığız.

Şimdiden teşekkürler.


Yanıtlarla ilgili düzenlemelerin size bildirilip bildirilmediğinden emin değilsiniz. Bu yüzden bu yorumu size kendi girintili döküm versiyonumu eklediğimi bildirmek için yazıyorum. :-)
PhiLho

Not: JSON.stringify () yanıtı, 'the' yanıtı olarak kabul edilmese de oldukça yararlı görünmektedir.
GuruM

Nodedump kullanarak nesnelerin görsel ve sezgisel bir çıktısını alabilirsiniz: github.com/ragamufin/nodedump
ragamufin

Yanıtlar:


31

Bir JS nesnesini okunabilir bir biçimde dökmek için bir işlev yazdım, ancak çıktı girintili olmasa da, bunu eklemek çok zor olmamalı: Bu işlevi Lua için yaptığım bir işlevden yaptım (ki bu çok daha karmaşık ) bu girinti sorununu ele alan.

İşte "basit" versiyon:

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

Biraz geliştirmeye bakacağım.
Not 1: Kullanmak od = DumpObject(something)için od.dump yapın ve kullanın. Konvolüsyonlu çünkü len değerini (öğe sayısı) başka bir amaç için istedim. İşlevin yalnızca dizgeyi döndürmesi önemsizdir.
Not 2: Referanslardaki döngüleri işlemez.

DÜZENLE

Girintili versiyonu yaptım.

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

Yinelemeli çağrı ile satırdaki girintinizi seçin ve bundan sonra yorumlu satırı değiştirerek stili destekleyin.

... kendi versiyonunu hazırladığını görüyorum, ki bu iyi. Ziyaretçilerin bir seçeneği olacak.


1
Seviyorum;) Düzgün çalışmasını sağlayamıyorum, ama sakıncası yoksa, utanmadan kavramı çalacağım ve kendi fikrimi yazacağım :)
Dan

2
Bu yaklaşımın kısa bir gelişi (Jason'ın önerdiği JSON.stringify yöntemiyle karşılaştırıldığında), nesne dizilerini düzgün şekilde göstermemesidir. Bir dizi nesneye sahip olduğunuzda, [nesne Nesnesi] olarak görünür.
Ryan

@Ryan: Tarayıcının yerel nesnelerini mi kastediyorsunuz? Evet, koduma dönüp baktığımda, bir yorum eklediğimi gördüm: // Bir alan bir nesne ise çok kötü ... :-P Tamam, burada testim için ... Kullanıcı tarafından yapılan yapıları dökmek sorun değil. Daha sağlam bir şeye ihtiyacınız varsa, aşağıda alternatifler olduğunu görüyorum.
PhiLho

Bunu kullanamam Bazı json verilerini atmaya çalıştığımda sonsuz döngü elde ediyorum.
neoneye

1
@RaphaelDDL & PhiLho - Maksimum çağrı yığını boyutu, küçük bir nesnede de tetiklenebilir; kendisine bir özellik referansı olan biri. Böyle bir referans, bu fonksiyonla sonsuz bir döngüye neden olur.
skibulk

233

Crockford'un JSON.stringify'ını şu şekilde kullanın :

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...

Değişken textşuna benzer:

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

Bu arada, bu JS dosyasından fazlasını gerektirmez - herhangi bir kitaplıkla vb. Çalışacaktır.


5
Bu neredeyse kesinlikle alacağınız en iyi cevap. 4 veya 5 programcı olmayanlara JSON.stringified veri yapılarını okumayı ve düzenlemeyi ve bunları yapılandırma dosyaları için kapsamlı bir şekilde kullanmayı öğrettim.
Joel Anair

1
Sorunlara neden olması garip - küresel ad alanına "JSON" adını getiriyor, bu nedenle sorunlara neden olabilir. Bir çakışma olup olmadığını görmek için bunu eklemeden önce ad alanınızda "JSON" olup olmadığını kontrol edin.
Jason Bunting

1
Eh, prototip böyle kötüdür ...;)
Jason Bunting

7
Firefox 3.5 ve üzeri ile ilgili bir güncelleme, JSON.stringify yerleşiktir. ( developer.mozilla.org/En/Using_JSON_in_Firefox ), bu nedenle yalnızca hata ayıklama amacıyla bir JSON nesnesi görmeye çalışıyorsanız, bunu fazladan JS bağımlılığı olmadan yapabilirsiniz.
Greg Bernhardt

3
Ayrıca Chrome'da. Ancak, JSON.stringify dairesel verilerde JSON.stringify((function(){var x = []; x.push(x); return x})())ve diğer birçok nesne türünde başarısız olur JSON.stringify(/foo/).
Kragen Javier Sitaker

21

Aşağıdakileri kullanabilirsiniz

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

15

İçinde Firebug, sadece console.debug ("%o", my_object)konsolda üzerine tıklayabilir ve etkileşimli bir nesne gezgini girebilirsiniz. Tüm nesneyi gösterir ve iç içe geçmiş nesneleri genişletmenize izin verir.


1
Bununla ilgili sorun, yalnızca 'en üstteki' nesneyi göstermesidir - düzinelerce iç içe nesnem var ve tüm içeriği aynı anda görebilmem ve daha da önemlisi, işlerin nerede değiştiğini görmem gerekiyor. Yani Firebug bu durumda benim için gerçekten işe yaramıyor.
Dan

(evet, genişletmek için tıklayabileceğinizi biliyorum, ancak veriyi her dökmek istediğimde 10 veya daha fazla bağlantıya tıklamak şu anda yaptığım şey - çok yavaş ilerleme)
Dan

1
Bu, Chrome'da da çalışır (ve bu nedenle muhtemelen Safari'de).
Kragen Javier Sitaker


9

Nesnenizi görmenin harika bir yolunu arayanlar için prettyPrint.js'yi kontrol edin

Dokümanınızın herhangi bir yerine yazdırılacak, yapılandırılabilir görünüm seçeneklerine sahip bir tablo oluşturur. Bakmaktan daha iyi console.

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

görüntü açıklamasını buraya girin


6

Programlıyorum Rhinove burada yayınlanan cevapların hiçbirinden memnun kalmadım. Bu yüzden kendi güzel yazıcımı yazdım:

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

Çıktı şuna benzer:

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

Ayrıca, gelecekte gerekli olabilecek değişiklikler için burada bir Özet olarak yayınladım .


7
Güzel bir yazıcı olabilir ama kod aslında pek hoş görünmüyor :)
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')
])

olur

[
   [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 tarafından kullanılan birim testi çerçevesi) jsDump'ın biraz yamalı sürümünü kullanan.


JSON.stringify () bazı durumlarda en iyi seçim değildir.

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

2

PhiLho'nun öncülüğünü alarak (çok teşekkürler :)), istediğim şeyi tam olarak yapamadığım için kendi başıma yazdım. Oldukça sert ve hazır, ama ihtiyacım olan işi yapıyor. Mükemmel önerileriniz için hepinize teşekkür ederim.

Harika bir kod değil, biliyorum, ama değeri ne olursa olsun, işte burada. Birisi onu faydalı bulabilir:

// 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
Bu arada, yapabilseniz bile, satırları noktalı virgül olmadan bitirmemelisiniz. Ayrıca, __ if (! Pad) pad = '' __ yapmanın standart yolu: __ pad = (pad || '') __
Jason Bunting

İf (! Foo) foo = ... vs foo = (foo || ...), ama tüm satırları noktalı virgülle bitirmenin mantığı nedir?
Dan

1
Bunu yapmazsanız, dilin bazı iğrenç özellikleriyle karşılaşacaksınız, ayrıca kodunuzu kolayca küçültemeyeceksiniz (kullandığınız minifier sizin için noktalı virgül koyacak kadar güzel değilse). Daha fazla ayrıntı için stackoverflow.com/questions/42247 adresine bakın.
Jason Bunting

1
eğer (! pad) pad = ''; daha ucuz, daha esnek ve pad = (pad || '') 'den daha okunaklı; küçük bir miktar da olsa. Bu formda ısrar ediyorsanız, gereksiz parantezi kaldırın. pad = pad || ''; Noktalı virgüllerin 3 nedeni: JS, bunları ihmal etmenin bir hata vereceğini gördüğünde uç satır noktalı virgüllerini otomatik olarak ekler. 1) Bu, kendiniz eklemekten biraz daha yavaştır ve 2) bir sonraki satır birleştirildiğinde bir hata atmadığında hatalara yol açabilir. 3) kodunuzun küçültülmesini önleyecektir.
SamGoody

1

Bu gerçekten Jason Bunting'in "Crockford'un JSON.stringify'ını kullan" üzerine bir yorum, ancak bu yanıta bir yorum ekleyemedim.

Yorumlarda belirtildiği gibi JSON.stringify, Prototype (www.prototypejs.org) kitaplığıyla iyi oynamıyor. Bununla birlikte, prototipin eklediği Array.prototype.toJSON yöntemini geçici olarak kaldırarak, Crockford'un stringify () yöntemini çalıştırarak ve ardından şu şekilde geri koyarak birlikte iyi oynamalarını sağlamak oldukça kolaydır:

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

1

J. Buntings'in JSON.stringify'ı kullanma konusundaki tepkisinin de iyi olduğunu düşündüm. YUI kullanıyorsanız, JSON.stringify'ı YUIs JSON nesnesi aracılığıyla kullanabilirsiniz. Benim durumumda, PhiLho yanıtını ince ayar / kesme / yapıştırma daha kolay olması için HTML'ye dökmem gerekiyordu.

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

Bu ileti dizisinde kod yazan birçok insan, çeşitli aldatmalarla ilgili birçok yorum yaptı. Bu çözümü beğendim çünkü eksiksiz görünüyordu ve bağımlılığı olmayan tek bir dosyaydı.

tarayıcı

nodejs

"Kutudan çıkar çıkmaz" işe yaradı ve hem düğüm hem de tarayıcı sürümlerine sahip (muhtemelen sadece farklı sarmalayıcılar ama onaylamak için kazmadım).

Kitaplık ayrıca oldukça iyi yazdırılan XML, SQL ve CSS'yi de destekliyor, ancak bu özellikleri denemedim.


0

Öğeleri dizeler olarak yazdırmak için basit bir yöntem:

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

Benim NeatJSON kütüphane hem Yakut ve sahip JavaScript sürümlerini . Bir (izin verilen) MIT Lisansı altında ücretsiz olarak temin edilebilir. Çevrimiçi bir demo / dönüştürücüyü şu adreste görüntüleyebilirsiniz:
http://phrogz.net/JS/neatjson/neatjson.html

Bazı özellikler (tümü isteğe bağlı):

  • Belirli bir genişliğe sarın; bir nesne veya dizi satıra sığabiliyorsa, tek satırda tutulur.
  • Bir nesnedeki tüm tuşlar için iki nokta üst üste işaretlerini hizalayın.
  • Anahtarları alfabetik olarak bir nesneye göre sıralayın.
  • Kayan nokta sayılarını belirli bir ondalık sayı olarak biçimlendirin.
  • Kaydırırken, diziler ve nesneler için açma / kapama parantezlerini ilk / son değerle aynı satıra koyan 'kısa' bir sürüm kullanın.
  • Diziler ve nesneler için boşlukları ayrıntılı bir şekilde kontrol edin (köşeli parantez içinde, iki nokta üst üste ve virgülden önce / sonra).
  • Web tarayıcısında ve Node.js modülü olarak çalışır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.