pretty-print - كيف يمكنني طباعة JSON باستخدام JavaScript؟




(17)

كيف يمكنني عرض JSON بتنسيق سهل القراءة (للقراء)؟ أنا أبحث في المقام الأول عن المسافة البادئة والفضاء ، وربما حتى الألوان / أنماط الخط / الخ.


Answers

واجهت مشكلة اليوم مع رمز @ Pumbaa80. أحاول تطبيق تمييز بنية JSON على البيانات التي Mithril عرض Mithril ، لذلك أحتاج إلى إنشاء عقد DOM لكل شيء في إخراج JSON.stringify .

أنا تقسيم regex طويلة حقا في مكوناته المكونة كذلك.

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)

كود في السياق على جيثب here


شكرا جزيلا @ كل! بناءً على الإجابات السابقة ، إليك طريقة متباينة أخرى تقدم قواعد الاستبدال المخصصة كمعلمة:

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


استخدم Newtonsoft.Json دلل. هذا يعمل بشكل جيد في IE و Chrome

ضع هذا الرمز في طريقة عرض الحلاقة

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


أوصي باستخدام HighlightJS . يستخدم نفس المبدأ مثل الإجابة المقبولة ، ولكنه يعمل أيضًا للعديد من اللغات الأخرى ، ويحتوي على العديد من أنظمة الألوان المعرفة مسبقًا . في حالة استخدام RequireJS ، يمكنك إنشاء وحدة نمطية متوافقة مع

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

يعتمد الجيل على Python3 و Java. إضافة -n لإنشاء نسخة غير مبسطة.


إليك كيفية الطباعة بدون استخدام الوظيفة الأصلية.

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

استنادًا إلى إجابة Pumbaa80 ، قمت بتعديل الشفرة لاستخدام ألوان console.log (التي تعمل على Chrome بالتأكيد) وليس HTML. يمكن رؤية الناتج داخل وحدة التحكم. يمكنك تحرير _ المتغيرات داخل الوظيفة مضيفا بعض أكثر التصميم.

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

في ما يلي مرجع مصور يمكنك استخدامه:

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

الاستعمال:

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

تعديل: حاولت فقط الهروب من رمز٪ بهذا السطر ، بعد إعلان المتغيرات:

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

ولكني أكتشف أن Chrome لا يدعم٪ escaping في وحدة التحكم. غريب ... ربما هذا سوف يعمل في المستقبل.

في صحتك!


هذا لطيف:

https://github.com/mafintosh/json-markup من mafintosh

const jsonMarkup = require('json-markup')
const html = jsonMarkup({hello:'world'})
document.querySelector('#myElem').innerHTML = html

HTML

<link ref="stylesheet" href="style.css">
<div id="myElem></div>

يمكن العثور على ورقة أنماط المثال هنا

https://raw.githubusercontent.com/mafintosh/json-markup/master/style.css

لم أكن NeatJSON عن الطابعات الأخرى الجميلة لروبي ، كتبت لي ( NeatJSON ) ومن ثم NeatJSON إلى JavaScript بما في ذلك منسق مجاني على الإنترنت . الرمز مجاني بموجب ترخيص معهد ماساتشوستس للتكنولوجيا (متسرع تماما).

الميزات (كل اختياري):

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

سأقوم بنسخ شفرة المصدر هنا بحيث لا يكون هذا مجرد رابط إلى مكتبة ، لكنني أشجعك على الانتقال إلى NeatJSON ، حيث سيتم تحديثها باستمرار ولن يتم إدخال الشفرة أدناه.

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

أستخدم ملحق JSONView Chrome (إنه جميل كما يحصل :):

تعديل: تمت إضافة jsonreport.js

لقد قمت أيضًا بإصدار عارض طباعة JSON قائم بذاته عبر الإنترنت ، jsonreport.js ، والذي يوفر تقرير HTML5 قابل للقراءة والذي يمكنك استخدامه لعرض أي بيانات JSON.

يمكنك قراءة المزيد عن التنسيق في تنسيق تقرير جافا سكريبت HTML5 الجديد .


إذا كنت تبحث عن مكتبة جميلة لتجعل json على صفحة ويب ...

Prism.js جيد جدا.

http://prismjs.com/

لقد وجدت استخدام JSON.stringify (obj، undefined، 2) للحصول على المسافة البادئة ، ثم استخدم المنشور لإضافة سمة طريقة جيدة.

إذا كنت تقوم بالتحميل في JSON عبر مكالمة ajax ، فيمكنك تشغيل أحد أساليب المساعدة الخاصة بـ Prism لإضفاء الطابع الشخصي

فمثلا:

Prism.highlightAll()

يمكنك استخدام console.dir() ، وهو اختصار لـ console.log(util.inspect()) . (والفرق الوحيد هو أنه يتجاوز أي وظيفة inspect() مخصصة inspect() محددة على كائن.)

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

const object = JSON.parse(jsonString)

console.dir(object, {depth: null, colors: true})

ولخط الأوامر:

cat package.json | node -e "process.stdin.pipe(new stream.Writable({write: chunk => console.dir(JSON.parse(chunk), {depth: null, colors: true})}))"


جواب المستخدم Pumbaa80 هو رائع إذا كان لديك كائن تريد طباعة جميلة. إذا كنت تبدأ من سلسلة JSON صالحة تريد طباعتها جيدًا ، فستحتاج إلى تحويلها إلى كائن أولاً:

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

يقوم هذا بإنشاء كائن JSON من السلسلة ، ثم يحوله مرة أخرى إلى سلسلة تستخدم طباعة JSON stringify الجميلة.


var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07",  "postalCode": "75007", "countryCode": "FRA",  "countryLabel": "France" };


document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);

// في حالة عرض HTML ، يجب عليك إضافة balise <pre> </ pre>

document.getElementById("result-after").innerHTML = "<pre>"+JSON.stringify(jsonObj,undefined, 2) +"</pre>"

إذا كنت بحاجة إلى هذا للعمل في أحد النصوص فلن يعمل الحل المقبول.

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

سنتى:

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

قليل من الأشياء المهمة التي تعلمتها بعد استخدام use strict :

يمنع الإعلان العالمي المتغير:

var tree1Data = { name: 'Banana Tree',age: 100,leafCount: 100000};

function Tree(typeOfTree) {
    var age;
    var leafCount;

    age = typeOfTree.age;
    leafCount = typeOfTree.leafCount;
    nameoftree = typeOfTree.name;
};

var tree1 = new Tree(tree1Data);
console.log(window);

الآن ، ينشئ هذا الرمز nameoftree في النطاق العالمي التي يمكن الوصول إليها باستخدام window.nameoftree . عندما ننفذ use strict رمى رمز الخطأ.

لم يتم تعريف referenceError: nameoftree

Sample

يقترن بالبيان:

with عبارات لا يمكن تقليلها باستخدام أدوات مثل uglify-js . كما يتم deprecated وإزالتها من إصدارات جافا سكريبت المستقبلية.

Sample

يمنع التكرارات:

عندما يكون لدينا خاصية مكررة ، فإنه يلقي استثناء

لم يتم سماح SyntaxError: خاصية بيانات مكررة في كائن حرفي في الوضع المقيد

"use strict";
var tree1Data = {
    name: 'Banana Tree',
    age: 100,
    leafCount: 100000,
    name:'Banana Tree'
};

هناك عدد قليل آخر ولكني بحاجة إلى اكتساب المزيد من المعرفة حول ذلك.





javascript json pretty-print