Pergunta

Eu estou tentando encontrar uma maneira de pretty print uma estrutura de dados JavaScript em um formato legível para depuração.

Eu tenho uma estrutura de dados bastante grande e complicado que está sendo armazenado em JS e eu preciso escrever algum código para manipulá-lo. A fim de descobrir o que estou fazendo e para onde estou indo errado, o que eu realmente preciso é ser capaz de ver a estrutura de dados em sua totalidade, e atualizá-lo sempre que fazer mudanças por meio da interface do usuário.

Todas essas coisas, sei me cuidar, além de encontrar uma boa maneira de despejar uma estrutura de dados JavaScript para uma string legível. JSON faria, mas ele realmente precisa ser bem formatado e recuado. Normalmente, eu usaria material excelente despejo DOM do Firebug para isso, mas eu realmente preciso para ser capaz de ver toda a estrutura de uma só vez, o que não parece ser possível em Firebug.

Todas as sugestões são bem-vindos.

Agradecemos antecipadamente.

Foi útil?

Solução

Eu escrevi uma função para despejar um objeto JS de uma forma legível, embora a saída não é recuado, mas não deve ser muito difícil de acrescentar que: Eu fiz esta função de um que fiz para Lua (que é muito mais complexo), que tratou este assunto recuo.

Aqui está a versão "simples":

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

vou olhar para melhorá-lo um pouco.
Nota 1: Para usá-lo, faça od = DumpObject(something) e usar od.dump. Complicado, porque eu queria o valor len também (número de itens) para outra finalidade. É trivial para fazer a função de retorno apenas o string.
Nota 2:. Não lidar com laços nas referências

Editar

Eu fiz a versão recuado.

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

Escolha o seu recuo na linha com a chamada recursiva, e você cinta estilo trocando a linha comentada após este.

... Eu vejo você chicoteado até a sua própria versão, que é bom. Os visitantes terão uma escolha.

Outras dicas

Use do Crockford JSON.stringify como este:

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 variável ficaria assim:

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

A propósito, este não requer nada mais do que isso arquivo JS -. Ele vai trabalhar com qualquer biblioteca, etc

Você pode usar o seguinte

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

Em Firebug, se você apenas console.debug ("%o", my_object) você pode clicar sobre ele no console e digite um explorador objeto interativo. Ela mostra todo o objeto, e permite expandir objetos aninhados.

Para Node.js, use:

util.inspect(object, [options]);

Documentação API

Para aqueles que procuram uma maneira impressionante para ver o seu objeto, verificar prettyPrint.js

cria uma tabela com opções de visualização configuráveis ??para ser impresso em algum lugar em seu doc. Melhor olhar do que no console.

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

enter descrição da imagem aqui

Estou programando em Rhino e eu não estava satisfeito com qualquer uma das respostas que foram postadas aqui. Então, eu escrevi minha própria impressora bastante:

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

Os olhares saída como esta:

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

Eu também postei-lo como um Gist aqui por qualquer mudanças futuro pode ser necessária.

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')
])

se torna

[
   [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 (quadro usado por jQuery Unidade de testes) usando versão ligeiramente corrigida do jsDump.


JSON.stringify () não é a melhor escolha em alguns casos.

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

Como tirar vantagem do PhiLho (muito obrigado :)), acabei escrevendo meu próprio como eu não conseguia obter o seu para fazer o que eu queria. É muito áspero e pronto, mas ele faz o trabalho da necessidade do eu. Obrigado a todos pelas excelentes sugestões.

Não é código brilhante, eu sei, mas o que vale a pena, aqui está. Alguém pode achar útil:

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

Isto é realmente apenas um comentário sobre Jason Bunting de "Usar Crockford JSON.stringify", mas não foi capaz de adicionar um comentário a essa resposta.

Como observado nos comentários, JSON.stringify não joga bem com a biblioteca Prototype (www.prototypejs.org). No entanto, é bastante fácil de fazê-los jogar bem juntos, removendo temporariamente o método Array.prototype.toJSON que protótipo acrescenta, execute stringify do Crockford (), em seguida, colocá-lo de volta como esta:

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

Eu pensei resposta J. Buntings sobre o uso JSON.stringify foi bom assim. A um lado, você pode usar JSON.stringify via YUIs JSON objeto se acontecer de você estar usando YUI. No meu caso eu precisava para despejar a HTML de modo que era mais fácil apenas ajustar cortar / colar resposta / 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;
}

Muitas pessoas que escrevem código neste segmento, com muitos comentários sobre diversas armadilhas. Eu gostei desta solução porque parecia completo e foi um único arquivo sem dependências.

navegador

nodejs

Ele trabalhou "fora da caixa" e tem duas versões de nó e do navegador (presumivelmente apenas diferentes invólucros mas eu não cavar para confirmar).

A biblioteca também suporta muito impressão XML, SQL e CSS, mas eu não tentei esses recursos.

A um simples para imprimir os elementos como strings:

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 biblioteca tem Ruby e versões JavaScript . É livremente disponível sob uma (permissiva) licença MIT. Você pode ver uma demo / conversor online em:
http://phrogz.net/JS/neatjson/neatjson.html

Alguns recursos (todos opcionais):

  • Enrole para uma largura específica; se um objeto ou matriz pode caber na linha, ele é mantido em uma linha.
  • Alinhar os dois pontos para todas as chaves em um objeto.
  • Classificar as chaves para um objeto em ordem alfabética.
  • Format números de ponto flutuante para um número específico de casas decimais.
  • Quando embrulho, use uma versão 'curta' que coloca os suportes de abrir / fechar para matrizes e objetos na mesma linha como o primeiro / último valor.
  • Controlo do espaço em branco para matrizes e os objectos de uma forma granular (dentro de parênteses, antes / depois de dois pontos e vírgulas).
  • Obras no navegador da web e como um módulo Node.js.

flexjson inclui uma função prettyPrint () que pode lhe dar o que você quer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top