JavaScript форматирование данных / симпатичный принтер - PullRequest
121 голосов
/ 25 сентября 2008

Я пытаюсь найти способ pretty print структуры данных JavaScript в удобочитаемой форме для отладки.

У меня довольно большая и сложная структура данных, хранящаяся в JS, и мне нужно написать некоторый код, чтобы манипулировать ею. Для того, чтобы понять, что я делаю и где я ошибаюсь, мне действительно нужно иметь возможность видеть структуру данных во всей ее полноте и обновлять ее всякий раз, когда я делаю изменения через пользовательский интерфейс.

Со всем этим я могу справиться сам, кроме поиска хорошего способа вывести структуру данных JavaScript в удобочитаемую строку. JSON подойдет, но он действительно должен быть красиво отформатирован и иметь отступ. Я бы обычно использовал для этого превосходные DOM-дампы Firebug, но мне действительно нужно было видеть всю структуру сразу, что в Firebug не представляется возможным.

Любые предложения приветствуются.

Заранее спасибо.

Ответы [ 15 ]

226 голосов
/ 25 сентября 2008

Использовать 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 - он будет работать с любой библиотекой и т. Д.

30 голосов
/ 25 сентября 2008

Я написал функцию для выгрузки 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: он не обрабатывает циклы в ссылках.

EDIT

Я сделал версию с отступом.

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

Выберите отступ в строке с рекурсивным вызовом, и вы закрепите стиль, переключив закомментированную строку после этой.

... Я вижу, вы взяли свою версию, и это хорошо. У посетителей будет выбор.

20 голосов
/ 23 июля 2012

Вы можете использовать следующие

<code><pre id="dump">
var dump = JSON.stringify (sampleJsonObject, null, 4); $ ( '# Свалка'). HTML (дамп)
15 голосов
/ 25 сентября 2008

В Firebug, если вы просто console.debug ("%o", my_object), вы можете нажать на нее в консоли и войти в интерактивный проводник объектов. Он показывает весь объект и позволяет раскрывать вложенные объекты.

11 голосов
/ 05 октября 2011

Для Node.js используйте:

util.inspect(object, [options]);

Документация по API

9 голосов
/ 21 июня 2013

Для тех, кто ищет потрясающий способ увидеть ваш объект, проверьте prettyPrint.js

Создает таблицу с настраиваемыми параметрами просмотра для печати где-нибудь на вашем документе. Лучше смотреть, чем в console.

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

enter image description here

6 голосов
/ 11 апреля 2011

Я программирую на 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 здесь для любых будущих изменений.

2 голосов
/ 19 февраля 2010

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
1 голос
/ 21 марта 2013

Множество людей, пишущих код в этой теме, со многими комментариями о различных ошибках. Мне понравилось это решение, потому что оно казалось законченным и представляло собой один файл без зависимостей.

браузер

nodejs

Он работал "из коробки" и имеет версии как для узла, так и для браузера (предположительно, просто разные обертки, но я не копал для подтверждения).

Библиотека также поддерживает красивую печать XML, SQL и CSS, но я не пробовал эти возможности.

1 голос
/ 29 марта 2011

Я думаю, что ответ Дж. Бантинга на использование JSON.stringify также был хорошим. Кроме того, вы можете использовать JSON.stringify через объект JSON YUI, если вы используете 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...