recorrer - string to json javascript




¿Cómo puedo imprimir JSON usando JavaScript? (16)

¿Cómo puedo mostrar JSON en un formato fácil de leer (para lectores humanos)? Estoy buscando principalmente sangrías y espacios en blanco, con quizás incluso colores / estilos de fuente / etc.


Aquí es cómo puede imprimir sin utilizar la función nativa.

function pretty(ob, lvl = 0) {

  let temp = [];

  if(typeof ob === "object"){
    for(let x in ob) {
      if(ob.hasOwnProperty(x)) {
        temp.push( getTabs(lvl+1) + x + ":" + pretty(ob[x], lvl+1) );
      }
    }
    return "{\n"+ temp.join(",\n") +"\n" + getTabs(lvl) + "}";
  }
  else {
    return ob;
  }

}

function getTabs(n) {
  let c = 0, res = "";
  while(c++ < n)
    res+="\t";
  return res;
}

let obj = {a: {b: 2}, x: {y: 3}};
console.log(pretty(obj));

/*
  {
    a: {
      b: 2
    },
    x: {
      y: 3
    }
  }
*/

Aquí está el impresionante HTML uno de user123444555621 adaptado para terminales. Práctico para la depuración de scripts de nodo:

function prettyJ(json) {
  if (typeof json !== 'string') {
    json = JSON.stringify(json, undefined, 2);
  }
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, 
    function (match) {
      let cls = "\x1b[36m";
      if (/^"/.test(match)) {
        if (/:$/.test(match)) {
          cls = "\x1b[34m";
        } else {
          cls = "\x1b[32m";
        }
      } else if (/true|false/.test(match)) {
        cls = "\x1b[35m"; 
      } else if (/null/.test(match)) {
        cls = "\x1b[31m";
      }
      return cls + match + "\x1b[0m";
    }
  );
}

Uso:

// thing = any json OR string of json
prettyJ(thing);

Basándome en la respuesta de Pumbaa80, modifiqué el código para usar los colores de console.log (seguro que funciona en Chrome) y no HTML. La salida se puede ver dentro de la consola. Puede editar las _variables dentro de la función agregando un poco más de estilo.

function JSONstringify(json) {
    if (typeof json != 'string') {
        json = JSON.stringify(json, undefined, '\t');
    }

    var 
        arr = [],
        _string = 'color:green',
        _number = 'color:darkorange',
        _boolean = 'color:blue',
        _null = 'color:magenta',
        _key = 'color:red';

    json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var style = _number;
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                style = _key;
            } else {
                style = _string;
            }
        } else if (/true|false/.test(match)) {
            style = _boolean;
        } else if (/null/.test(match)) {
            style = _null;
        }
        arr.push(style);
        arr.push('');
        return '%c' + match + '%c';
    });

    arr.unshift(json);

    console.log.apply(console, arr);
}

Aquí hay un bookmarklet que puedes usar:

javascript:function JSONstringify(json) {if (typeof json != 'string') {json = JSON.stringify(json, undefined, '\t');}var arr = [],_string = 'color:green',_number = 'color:darkorange',_boolean = 'color:blue',_null = 'color:magenta',_key = 'color:red';json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {var style = _number;if (/^"/.test(match)) {if (/:$/.test(match)) {style = _key;} else {style = _string;}} else if (/true|false/.test(match)) {style = _boolean;} else if (/null/.test(match)) {style = _null;}arr.push(style);arr.push('');return '%c' + match + '%c';});arr.unshift(json);console.log.apply(console, arr);};void(0);

Uso:

var obj = {a:1, 'b':'foo', c:[false,null, {d:{e:1.3e5}}]};
JSONstringify(obj);

Edición: Acabo de intentar escapar del símbolo% con esta línea, después de la declaración de las variables:

json = json.replace(/%/g, '%%');

Pero descubro que Chrome no admite el% de escape en la consola. Extraño ... Tal vez esto funcione en el futuro.

¡Aclamaciones!




Insatisfecho con otras impresoras bonitas para Ruby, escribí la mía ( NeatJSON ) y luego la NeatJSON a JavaScript, incluido un formateador en línea gratuito . El código es gratuito bajo licencia MIT (bastante permisivo).

Características (todas opcionales):

  • Establezca un ancho de línea y ajuste de forma que mantenga los objetos y las matrices en la misma línea cuando encajen, envolviendo un valor por línea cuando no lo hacen.
  • Ordena las llaves de los objetos si quieres.
  • Alinear claves de objeto (alinear los dos puntos).
  • Formatee números de punto flotante a un número específico de decimales, sin desordenar los enteros.
  • El modo de ajuste 'Corto' pone los corchetes / llaves de apertura y cierre en la misma línea que los valores, proporcionando un formato que algunos prefieren.
  • Control granular sobre el espacio entre matrices y objetos, entre paréntesis, antes y después de dos puntos y comas.
  • La función está disponible para los navegadores web y Node.js.

Copiaré el código fuente aquí para que esto no sea solo un enlace a una biblioteca, sino que lo aliento a que vaya a la NeatJSON , ya que se mantendrá actualizado y el código a continuación no lo hará.

(function(exports){
exports.neatJSON = neatJSON;

function neatJSON(value,opts){
  opts = opts || {}
  if (!('wrap'          in opts)) opts.wrap = 80;
  if (opts.wrap==true) opts.wrap = -1;
  if (!('indent'        in opts)) opts.indent = '  ';
  if (!('arrayPadding'  in opts)) opts.arrayPadding  = ('padding' in opts) ? opts.padding : 0;
  if (!('objectPadding' in opts)) opts.objectPadding = ('padding' in opts) ? opts.padding : 0;
  if (!('afterComma'    in opts)) opts.afterComma    = ('aroundComma' in opts) ? opts.aroundComma : 0;
  if (!('beforeComma'   in opts)) opts.beforeComma   = ('aroundComma' in opts) ? opts.aroundComma : 0;
  if (!('afterColon'    in opts)) opts.afterColon    = ('aroundColon' in opts) ? opts.aroundColon : 0;
  if (!('beforeColon'   in opts)) opts.beforeColon   = ('aroundColon' in opts) ? opts.aroundColon : 0;

  var apad  = repeat(' ',opts.arrayPadding),
      opad  = repeat(' ',opts.objectPadding),
      comma = repeat(' ',opts.beforeComma)+','+repeat(' ',opts.afterComma),
      colon = repeat(' ',opts.beforeColon)+':'+repeat(' ',opts.afterColon);

  return build(value,'');

  function build(o,indent){
    if (o===null || o===undefined) return indent+'null';
    else{
      switch(o.constructor){
        case Number:
          var isFloat = (o === +o && o !== (o|0));
          return indent + ((isFloat && ('decimals' in opts)) ? o.toFixed(opts.decimals) : (o+''));

        case Array:
          var pieces  = o.map(function(v){ return build(v,'') });
          var oneLine = indent+'['+apad+pieces.join(comma)+apad+']';
          if (opts.wrap===false || oneLine.length<=opts.wrap) return oneLine;
          if (opts.short){
            var indent2 = indent+' '+apad;
            pieces = o.map(function(v){ return build(v,indent2) });
            pieces[0] = pieces[0].replace(indent2,indent+'['+apad);
            pieces[pieces.length-1] = pieces[pieces.length-1]+apad+']';
            return pieces.join(',\n');
          }else{
            var indent2 = indent+opts.indent;
            return indent+'[\n'+o.map(function(v){ return build(v,indent2) }).join(',\n')+'\n'+indent+']';
          }

        case Object:
          var keyvals=[],i=0;
          for (var k in o) keyvals[i++] = [JSON.stringify(k), build(o[k],'')];
          if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
          keyvals = keyvals.map(function(kv){ return kv.join(colon) }).join(comma);
          var oneLine = indent+"{"+opad+keyvals+opad+"}";
          if (opts.wrap===false || oneLine.length<opts.wrap) return oneLine;
          if (opts.short){
            var keyvals=[],i=0;
            for (var k in o) keyvals[i++] = [indent+' '+opad+JSON.stringify(k),o[k]];
            if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
            keyvals[0][0] = keyvals[0][0].replace(indent+' ',indent+'{');
            if (opts.aligned){
              var longest = 0;
              for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
              var padding = repeat(' ',longest);
              for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
            }
            for (var i=keyvals.length;i--;){
              var k=keyvals[i][0], v=keyvals[i][1];
              var indent2 = repeat(' ',(k+colon).length);
              var oneLine = k+colon+build(v,'');
              keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
            }
            return keyvals.join(',\n') + opad + '}';
          }else{
            var keyvals=[],i=0;
            for (var k in o) keyvals[i++] = [indent+opts.indent+JSON.stringify(k),o[k]];
            if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
            if (opts.aligned){
              var longest = 0;
              for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
              var padding = repeat(' ',longest);
              for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
            }
            var indent2 = indent+opts.indent;
            for (var i=keyvals.length;i--;){
              var k=keyvals[i][0], v=keyvals[i][1];
              var oneLine = k+colon+build(v,'');
              keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
            }
            return indent+'{\n'+keyvals.join(',\n')+'\n'+indent+'}'
          }

        default:
          return indent+JSON.stringify(o);
      }
    }
  }

  function repeat(str,times){ // http://.com/a/17800645/405017
    var result = '';
    while(true){
      if (times & 1) result += str;
      times >>= 1;
      if (times) str += str;
      else break;
    }
    return result;
  }
  function padRight(pad, str){
    return (str + pad).substring(0, pad.length);
  }
}
neatJSON.version = "0.5";

})(typeof exports === 'undefined' ? this : exports);

La respuesta del usuario Pumbaa80 es excelente si tiene un objeto que desea imprimir bastante. Si está comenzando desde una cadena JSON válida que desea imprimir bastante, primero debe convertirla en un objeto:

var jsonString = '{"some":"json"}';
var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);  

Esto construye un objeto JSON a partir de la cadena, y luego lo convierte de nuevo en una cadena usando la impresión bonita de JSON.


Me encontré con un problema hoy con el código de @Pumbaa80. Estoy tratando de aplicar el resaltado de sintaxis JSON a los datos que estoy representando en una vista de Mithril , por lo que necesito crear nodos DOM para todo lo que JSON.stringify en la salida de JSON.stringify .

También dividí la expresión regular realmente larga en sus partes componentes.

render_json = (data) ->
  # wraps JSON data in span elements so that syntax highlighting may be
  # applied. Should be placed in a `whitespace: pre` context
  if typeof(data) isnt 'string'
    data = JSON.stringify(data, undefined, 2)
  unicode =     /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/
  keyword =     /\b(true|false|null)\b/
  whitespace =  /\s+/
  punctuation = /[,.}{\[\]]/
  number =      /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/

  syntax = '(' + [unicode, keyword, whitespace,
            punctuation, number].map((r) -> r.source).join('|') + ')'
  parser = new RegExp(syntax, 'g')

  nodes = data.match(parser) ? []
  select_class = (node) ->
    if punctuation.test(node)
      return 'punctuation'
    if /^\s+$/.test(node)
      return 'whitespace'
    if /^\"/.test(node)
      if /:$/.test(node)
        return 'key'
      return 'string'

    if /true|false/.test(node)
      return 'boolean'

     if /null/.test(node)
       return 'null'
     return 'number'
  return nodes.map (node) ->
    cls = select_class(node)
    return Mithril('span', {class: cls}, node)

Código en contexto en Github here


Muchas gracias @todos! Basado en las respuestas anteriores, aquí hay otro método de variante que proporciona reglas de reemplazo personalizadas como parámetro:

 renderJSON : function(json, rr, code, pre){
   if (typeof json !== 'string') {
      json = JSON.stringify(json, undefined, '\t');
   }
  var rules = {
   def : 'color:black;',    
   defKey : function(match){
             return '<strong>' + match + '</strong>';
          },
   types : [
       {
          name : 'True',
          regex : /true/,
          type : 'boolean',
          style : 'color:lightgreen;'
       },

       {
          name : 'False',
          regex : /false/,
          type : 'boolean',
          style : 'color:lightred;'
       },

       {
          name : 'Unicode',
          regex : /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/,
          type : 'string',
          style : 'color:green;'
       },

       {
          name : 'Null',
          regex : /null/,
          type : 'nil',
          style : 'color:magenta;'
       },

       {
          name : 'Number',
          regex : /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/,
          type : 'number',
          style : 'color:darkorange;'
       },

       {
          name : 'Whitespace',
          regex : /\s+/,
          type : 'whitespace',
          style : function(match){
             return '&nbsp';
          }
       } 

    ],

    keys : [
       {
           name : 'Testkey',
           regex : /("testkey")/,
           type : 'key',
           style : function(match){
             return '<h1>' + match + '</h1>';
          }
       }
    ],

    punctuation : {
          name : 'Punctuation',
          regex : /([\,\.\}\{\[\]])/,
          type : 'punctuation',
          style : function(match){
             return '<p>________</p>';
          }
       }

  };

  if('undefined' !== typeof jQuery){
     rules = $.extend(rules, ('object' === typeof rr) ? rr : {});  
  }else{
     for(var k in rr ){
        rules[k] = rr[k];
     }
  }
    var str = json.replace(/([\,\.\}\{\[\]]|"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
    var i = 0, p;
    if (rules.punctuation.regex.test(match)) {
               if('string' === typeof rules.punctuation.style){
                   return '<span style="'+ rules.punctuation.style + '">' + match + '</span>';
               }else if('function' === typeof rules.punctuation.style){
                   return rules.punctuation.style(match);
               } else{
                  return match;
               }            
    }

    if (/^"/.test(match)) {
        if (/:$/.test(match)) {
            for(i=0;i<rules.keys.length;i++){
            p = rules.keys[i];
            if (p.regex.test(match)) {
               if('string' === typeof p.style){
                   return '<span style="'+ p.style + '">' + match + '</span>';
               }else if('function' === typeof p.style){
                   return p.style(match);
               } else{
                  return match;
               }                
             }              
           }   
            return ('function'===typeof rules.defKey) ? rules.defKey(match) : '<span style="'+ rules.defKey + '">' + match + '</span>';            
        } else {
            return ('function'===typeof rules.def) ? rules.def(match) : '<span style="'+ rules.def + '">' + match + '</span>';
        }
    } else {
        for(i=0;i<rules.types.length;i++){
         p = rules.types[i];
         if (p.regex.test(match)) {
               if('string' === typeof p.style){
                   return '<span style="'+ p.style + '">' + match + '</span>';
               }else if('function' === typeof p.style){
                   return p.style(match);
               } else{
                  return match;
               }                
          }             
        }

     }

    });

  if(true === pre)str = '<pre>' + str + '</pre>';
  if(true === code)str = '<code>' + str + '</code>';
  return str;
 }


Puede usar JSON.stringify (su objeto, nulo, 2) El segundo parámetro puede usarse como una función de reemplazo que toma la clave y Val como parámetros. Esto puede usarse en caso de que quiera modificar algo dentro de su objeto JSON.


Recomiendo usar HighlightJS . Utiliza el mismo principio que la respuesta aceptada, pero funciona también para muchos otros idiomas y tiene muchos esquemas de color predefinidos . Si usa RequireJS , puede generar un módulo compatible con

python3 tools/build.py -tamd json xml <specify other language here>

La generación se basa en Python3 y Java. Agregue -n para generar una versión no minificada.


Si necesita que esto funcione en un área de texto, la solución aceptada no funcionará.

<textarea id='textarea'></textarea>

$("#textarea").append(formatJSON(JSON.stringify(jsonobject),true));

function formatJSON(json,textarea) {
    var nl;
    if(textarea) {
        nl = "&#13;&#10;";
    } else {
        nl = "<br>";
    }
    var tab = "&#160;&#160;&#160;&#160;";
    var ret = "";
    var numquotes = 0;
    var betweenquotes = false;
    var firstquote = false;
    for (var i = 0; i < json.length; i++) {
        var c = json[i];
        if(c == '"') {
            numquotes ++;
            if((numquotes + 2) % 2 == 1) {
                betweenquotes = true;
            } else {
                betweenquotes = false;
            }
            if((numquotes + 3) % 4 == 0) {
                firstquote = true;
            } else {
                firstquote = false;
            }
        }

        if(c == '[' && !betweenquotes) {
            ret += c;
            ret += nl;
            continue;
        }
        if(c == '{' && !betweenquotes) {
            ret += tab;
            ret += c;
            ret += nl;
            continue;
        }
        if(c == '"' && firstquote) {
            ret += tab + tab;
            ret += c;
            continue;
        } else if (c == '"' && !firstquote) {
            ret += c;
            continue;
        }
        if(c == ',' && !betweenquotes) {
            ret += c;
            ret += nl;
            continue;
        }
        if(c == '}' && !betweenquotes) {
            ret += nl;
            ret += tab;
            ret += c;
            continue;
        }
        if(c == ']' && !betweenquotes) {
            ret += nl;
            ret += c;
            continue;
        }
        ret += c;
    } // i loop
    return ret;
}

Si usa net.sf.json, puede imprimir de la siguiente manera (utilizando una sangría de 4 espacios):

JSONObject work = JSONObject.fromObject("{\"hi\":\"there\",\"more\":\"stuff\"}");
log.info("WORK="+work.toString(4));

La impresión bonita se implementa de forma nativa en JSON.stringify() . El tercer argumento permite una impresión bonita y establece el espacio a utilizar:

var str = JSON.stringify(obj, null, 2); // spacing level = 2

Si necesita resaltado de sintaxis, puede usar algo de magia de expresiones regulares como:

function syntaxHighlight(json) {
    if (typeof json != 'string') {
         json = JSON.stringify(json, undefined, 2);
    }
    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'key';
            } else {
                cls = 'string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'boolean';
        } else if (/null/.test(match)) {
            cls = 'null';
        }
        return '<span class="' + cls + '">' + match + '</span>';
    });
}

Ver en acción aquí: jsfiddle

O un fragmento completo a continuación:

function output(inp) {
    document.body.appendChild(document.createElement('pre')).innerHTML = inp;
}

function syntaxHighlight(json) {
    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'key';
            } else {
                cls = 'string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'boolean';
        } else if (/null/.test(match)) {
            cls = 'null';
        }
        return '<span class="' + cls + '">' + match + '</span>';
    });
}

var obj = {a:1, 'b':'foo', c:[false,'false',null, 'null', {d:{e:1.3e5,f:'1.3e5'}}]};
var str = JSON.stringify(obj, undefined, 4);

output(str);
output(syntaxHighlight(str));
pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }


Utilice Newtonsoft.Json dll. Esto funciona bien en IE y Chrome

ponga este código en su vista de afeitar

    if (Model.YourJsonSting!= null)
        {
            <pre>
            <code style="display:block;white-space:pre-wrap">
                      @JToken.Parse(Model.YourJsonSting).ToString(Formatting.Indented)
                </code>
            </pre>
        }




pretty-print