سؤال

أحاول أن أجد طريقة لذلك pretty print بنية بيانات JavaScript في نموذج يمكن قراءته من قبل الإنسان لتصحيح الأخطاء.

لدي بنية بيانات كبيرة ومعقدة إلى حد ما يتم تخزينها في JS وأحتاج إلى كتابة بعض التعليمات البرمجية لمعالجتها.من أجل معرفة ما أفعله وأين أخطئ، ما أحتاجه حقًا هو أن أكون قادرًا على رؤية بنية البيانات بالكامل، وتحديثها كلما قمت بإجراء تغييرات من خلال واجهة المستخدم.

يمكنني التعامل مع كل هذه الأشياء بنفسي، بصرف النظر عن إيجاد طريقة لطيفة لتفريغ بنية بيانات JavaScript إلى سلسلة يمكن قراءتها بواسطة الإنسان.سوف يقوم JSON بذلك، لكنه يحتاج حقًا إلى التنسيق والمسافة البادئة بشكل جيد.عادةً ما أستخدم عناصر تفريغ DOM الممتازة من Firebug لهذا الغرض، ولكنني أحتاج حقًا إلى أن أكون قادرًا على رؤية البنية بأكملها مرة واحدة، وهو ما لا يبدو ممكنًا في Firebug.

أي اقتراحات هي موضع ترحيب.

شكرا لك مقدما.

هل كانت مفيدة؟

المحلول

لقد كتبت دالة لتفريغ كائن 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$/, "");
}

اختر المسافة البادئة الخاصة بك على السطر الذي يحتوي على الاستدعاء العودي، وقم بضبط النمط عن طريق تبديل السطر الذي تم التعليق عليه بعد هذا السطر.

...أرى أنك قمت بإعداد نسختك الخاصة، وهو أمر جيد.سيكون للزوار الاختيار.

نصائح أخرى

يستخدم كروكفورد 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 - فهو سيعمل مع أي مكتبة، وما إلى ذلك.

يمكنك استخدام ما يلي

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

في Firebug, ، إذا كنت فقط console.debug ("%o", my_object) يمكنك النقر عليه في وحدة التحكم والدخول إلى مستكشف الكائنات التفاعلي.فهو يُظهر الكائن بأكمله، ويتيح لك توسيع الكائنات المتداخلة.

بالنسبة إلى Node.js، استخدم:

util.inspect(object, [options]);

وثائق واجهة برمجة التطبيقات

لأولئك الذين يبحثون عن طريقة رائعة لرؤية الشيء الخاص بك، تحقق من PrettyPrint.js

ينشئ جدولاً بخيارات عرض قابلة للتكوين لتتم طباعته في مكان ما على مستندك.أفضل أن ننظر من في console.

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

enter image description here

أنا أبرمج في 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: []
    }
}

لقد قمت بنشره أيضًا كـ جوهر هنا لأية تغييرات مستقبلية قد تكون مطلوبة.

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">
]

كيونيت (إطار عمل اختبار الوحدة الذي يستخدمه jQuery) باستخدام إصدار مصحح قليلاً من jsDump.


JSON.stringify() ليس الخيار الأفضل في بعض الحالات.

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

بأخذ زمام المبادرة من 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
}

هذا في الواقع مجرد تعليق على "استخدم JSON.stringify الخاص بـ Jason Bunting"، لكنني لم أتمكن من إضافة تعليق إلى تلك الإجابة.

كما هو مذكور في التعليقات، JSON.stringify لا يعمل بشكل جيد مع مكتبة النموذج الأولي (www.prototypejs.org).ومع ذلك، فمن السهل إلى حد ما جعلها تعمل بشكل جيد معًا عن طريق إزالة طريقة Array.prototype.toJSON التي يضيفها النموذج الأولي مؤقتًا، وتشغيل Crockford's stringify()، ثم إعادتها مرة أخرى مثل هذا:

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

اعتقدت ج.كانت استجابة Buntings عند استخدام JSON.stringify جيدة أيضًا.بالإضافة إلى ذلك، يمكنك استخدام JSON.stringify عبر كائن YUIs JSON إذا كنت تستخدم YUI.في حالتي كنت بحاجة إلى التفريغ إلى 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;
}

يكتب الكثير من الأشخاص التعليمات البرمجية في هذا الموضوع، مع العديد من التعليقات حول العديد من الأخطاء.لقد أحببت هذا الحل لأنه بدا كاملاً وكان ملفًا واحدًا بدون تبعيات.

browser

معرف com لهذا التطبيق هو com.nodejs

لقد كان يعمل "خارج الصندوق" ويحتوي على إصدارات العقدة والمتصفح (يُفترض أنها مجرد أغلفة مختلفة لكنني لم أتعمق للتأكيد).

تدعم المكتبة أيضًا طباعة XML وSQL وCSS بشكل جميل، لكنني لم أجرب هذه الميزات.

طريقة بسيطة لطباعة العناصر كسلاسل:

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

لي NeatJSON تحتوي المكتبة على كل من Ruby و إصدارات جافا سكريبت.إنه متاح مجانًا بموجب ترخيص MIT (المسموح به).يمكنك مشاهدة العرض التوضيحي/المحول عبر الإنترنت على:
http://phrogz.net/JS/neatjson/neatjson.html

بعض الميزات (كلها اختيارية):

  • التفاف لعرض معين.إذا كان من الممكن احتواء كائن أو مصفوفة على الخط، فسيتم الاحتفاظ به على سطر واحد.
  • قم بمحاذاة النقطتين لجميع المفاتيح في الكائن.
  • فرز المفاتيح إلى كائن أبجديا.
  • تنسيق أرقام الفاصلة العائمة إلى عدد محدد من الكسور العشرية.
  • عند الالتفاف، استخدم إصدارًا "قصيرًا" يضع أقواس الفتح/الإغلاق للمصفوفات والكائنات على نفس السطر مثل القيمة الأولى/الأخيرة.
  • تحكم في المسافة البيضاء للمصفوفات والكائنات بطريقة تفصيلية (داخل الأقواس، قبل/بعد النقطتين والفواصل).
  • يعمل في متصفح الويب وكوحدة Node.js.

flexjson يتضمن وظيفة PrettyPrint() التي قد تمنحك ما تريد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top