web-dev-qa-db-fra.com

Format de données JavaScript / jolie imprimante

J'essaie de trouver un moyen de pretty print une structure de données JavaScript sous une forme lisible par l'homme pour le débogage.

J'ai une structure de données plutôt grosse et compliquée stockée dans JS et j'ai besoin d'écrire du code pour le manipuler. Afin de comprendre ce que je fais et ce qui ne va pas, je dois avant tout pouvoir visualiser la structure de données dans son intégralité et la mettre à jour chaque fois que je modifie l'interface utilisateur.

Je peux me débrouiller avec tout cela, en plus de trouver un moyen agréable de dumper une structure de données JavaScript dans une chaîne lisible par l'homme. JSON ferait l'affaire, mais il doit vraiment être bien formaté et mis en retrait. Pour ce faire, j'utilise généralement l'excellent logiciel DOM de Firebug, mais je dois vraiment pouvoir visualiser l'ensemble de la structure à la fois, ce qui ne semble pas possible dans Firebug.

Toutes les suggestions sont les bienvenues.

Merci d'avance.

123
Dan

J'ai écrit une fonction pour vider un objet JS sous une forme lisible, bien que la sortie ne soit pas indentée, mais il ne devrait pas être trop difficile de l'ajouter: j'ai créé cette fonction à partir de celle que j'ai faite pour Lua (qui est beaucoup plus complexe ) qui traitait ce problème d’indentation.

Voici la version "simple":

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

Je vais chercher à l'améliorer un peu.
Note 1: Pour l'utiliser, utilisez od = DumpObject(something) et utilisez od.dump. Convolué parce que je voulais aussi la valeur len (nombre d'éléments) à une autre fin. Il est trivial de faire en sorte que la fonction ne renvoie que la chaîne.
Note 2: il ne gère pas les boucles dans les références.

EDIT

J'ai fait la version en retrait.

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

Choisissez votre mise en retrait sur la ligne avec l'appel récursif et vous consolidez le style en changeant la ligne commentée après celle-ci.

... Je vois que vous avez préparé votre propre version, ce qui est bien. Les visiteurs auront le choix.

30
PhiLho

Utilisez JSON.stringify de Crockford comme ceci:

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

La variable text ressemblerait à ceci:

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

En passant, cela ne nécessite rien de plus que ce fichier JS - cela fonctionnera avec n’importe quelle bibliothèque, etc.

228
Jason Bunting

Vous pouvez utiliser ce qui suit

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

Dans Firebug, si vous ne faites que console.debug ("%o", my_object), vous pouvez cliquer dessus dans la console et entrer un explorateur d'objet interactif. Il montre l'objet entier et vous permet de développer des objets imbriqués.

15
John Millikin

Pour Node.js, utilisez:

util.inspect(object, [options]);

Documentation API

11
Davem M

Pour ceux qui recherchent un moyen génial de voir votre objet, check prettyPrint.js

Crée un tableau avec des options d'affichage configurables à imprimer quelque part sur votre doc. Mieux vaut regarder que dans le console.

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

enter image description here

9
RaphaelDDL

Je programme en Rhino et je n’étais satisfait d’aucune des réponses publiées ici. J'ai donc écrit ma propre jolie imprimante:

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

La sortie ressemble à ceci:

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

Je l'ai également posté en tant que Gist here pour les modifications futures qui pourraient être nécessaires.

6
knowtheory

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

devient

[
   [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 (framework de tests unitaires utilisé par jQuery) utilisant une version légèrement corrigée de jsDump.


JSON.stringify () n'est pas le meilleur choix dans certains cas.

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

Prenant l'exemple de PhiLho (merci beaucoup :)), j'ai fini par écrire le mien car je ne pouvais pas le faire faire ce que je voulais. C'est assez difficile et prêt, mais il fait le travail dont j'ai besoin. Merci à tous pour les excellentes suggestions.

Ce n'est pas un code brillant, je sais, mais pour ce que ça vaut, le voici. Quelqu'un pourrait le trouver utile:

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

Beaucoup de gens écrivent du code dans ce fil, avec de nombreux commentaires sur divers pièges. J'ai aimé cette solution car elle semblait complète et constituait un seul fichier sans dépendance.

navigateur

nodejs

Cela fonctionnait "out of the box" et comportait à la fois des versions de nœud et de navigateur (vraisemblablement des emballages différents, mais je n'ai pas encore Dig pour confirmer).

La bibliothèque prend également en charge les jolies impressions XML, SQL et CSS, mais je n’ai pas essayé ces fonctionnalités.

1
mm2001

Je pensais que la réponse de J. Buntings à l’utilisation de JSON.stringify était également bonne. De plus, vous pouvez utiliser JSON.stringify via l’objet JSON YUIs si vous utilisez YUI. Dans mon cas, je devais passer au HTML, il était donc plus facile de tordre/couper/coller une réponse 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
GTM

Ceci est vraiment juste un commentaire sur "Utilisez JSON.stringify de Crockford", mais je n'ai pas pu ajouter de commentaire à cette réponse.

Comme indiqué dans les commentaires, JSON.stringify ne fonctionne pas bien avec la bibliothèque Prototype (www.prototypejs.org). Cependant, il est assez facile de les faire bien jouer en supprimant temporairement la méthode Array.prototype.toJSON ajoutée par le prototype, exécutez stringify () de Crockford, puis remettez-le comme ceci:

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

Un simple pour imprimer les éléments sous forme de chaînes:

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
aliteralmind

Ma bibliothèque NeatJSON possède à la fois Ruby et versions JavaScript . Il est disponible gratuitement sous une licence (permissive) MIT. Vous pouvez voir une démo/convertisseur en ligne sur:
http://phrogz.net/JS/neatjson/neatjson.html

Quelques fonctionnalités (toutes optionnelles):

  • Envelopper à une largeur spécifique; si un objet ou un tableau peut tenir sur la ligne, il est conservé sur une ligne.
  • Alignez les deux points pour toutes les clés d'un objet.
  • Triez les clés d'un objet par ordre alphabétique.
  • Formatez les nombres à virgule flottante en un nombre spécifique de décimales.
  • Lors du retour à la ligne, utilisez une version 'courte' qui place les crochets d'ouverture/fermeture pour les tableaux et les objets sur la même ligne que la première/dernière valeur.
  • Contrôlez les espaces pour les tableaux et les objets de manière granulaire (entre crochets, avant/après les deux points et les virgules).
  • Fonctionne dans le navigateur Web et en tant que module Node.js.
0
Phrogz