How can I display JSON in an easy-to-read (for human readers) format? I'm looking primarily for indentation and whitespace, with perhaps even colors / font-styles / etc.
问题:
回答1:
Pretty-printing is implemented natively in JSON.stringify()
. The third argument enables pretty printing and sets the spacing to use:
var str = JSON.stringify(obj, null, 2); // spacing level = 2
If you need syntax highlighting, you might use some regex magic like so:
function syntaxHighlight(json) { if (typeof json != 'string') { json = JSON.stringify(json, undefined, 2); } json = json.replace(/&/g, '&').replace(//g, '>'); 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 '' + match + ''; }); }
See in action here: jsfiddle
Or a full snippet provided below:
function output(inp) { document.body.appendChild(document.createElement('pre')).innerHTML = inp; } function syntaxHighlight(json) { json = json.replace(/&/g, '&').replace(//g, '>'); 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 '' + match + ''; }); } 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; }
回答2:
User Pumbaa80's answer is great if you have an object you want pretty printed. If you're starting from a valid JSON string that you want to pretty printed, you need to convert it to an object first:
var jsonString = '{"some":"json"}'; var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);
This builds a JSON object from the string, and then converts it back to a string using JSON stringify's pretty print.
回答3:
Based on Pumbaa80's answer I have modified the code to use the console.log colours (working on Chrome for sure) and not HTML. Output can be seen inside console. You can edit the _variables inside the function adding some more styling.
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); }
Here is a bookmarklet you can use:
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);
Usage:
var obj = {a:1, 'b':'foo', c:[false,null, {d:{e:1.3e5}}]}; JSONstringify(obj);
Edit: I just tried to escape the % symbol with this line, after the variables declaration:
json = json.replace(/%/g, '%%');
But I find out that Chrome is not supporting % escaping in the console. Strange... Maybe this will work in the future.
Cheers!
回答4:
I use the JSONView Chrome extension (it is as pretty as it gets :):
Edit: added jsonreport.js
I've also released an online stand-alone JSON pretty print viewer, jsonreport.js, that provides a human readable HTML5 report you can use to view any JSON data.
You can read more about the format in New JavaScript HTML5 Report Format.
回答5:
You can use console.dir()
, which is a shortcut for console.log(util.inspect())
. (The only difference is that it bypasses any custom inspect()
function defined on an object.)
It uses syntax-highlighting, smart indentation, removes quotes from keys and just makes the output as pretty as it gets.
const object = JSON.parse(jsonString) console.dir(object, {depth: null, colors: true})
and for the command line:
cat package.json | node -e "process.stdin.pipe(new stream.Writable({write: chunk => console.dir(JSON.parse(chunk), {depth: null, colors: true})}))"
回答6:
回答7:
For debugging purpose I use:
console.debug("%o", data);
回答8:
var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07", "postalCode": "75007", "countryCode": "FRA", "countryLabel": "France" }; document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);
// in case of displaying in HTML, you should to add a balise < pre>< /pre>
document.getElementById("result-after").innerHTML = ""+JSON.stringify(jsonObj,undefined, 2) +"
"
回答9:
Unsatisfied with other pretty printers for Ruby, I wrote my own (NeatJSON) and then ported it to JavaScript including a free online formatter. The code is free under MIT license (quite permissive).
Features (all optional):
- Set a line width and wrap in a way that keeps objects and arrays on the same line when they fit, wrapping one value per line when they don't.
- Sort object keys if you like.
- Align object keys (line up the colons).
- Format floating point numbers to specific number of decimals, without messing up the integers.
- 'Short' wrapping mode puts opening and closing brackets/braces on the same line as values, providing a format that some prefer.
- Granular control over spacing for arrays and objects, between brackets, before/after colons and commas.
- Function is made available to both web browsers and Node.js.
I'll copy the source code here so that this is not just a link to a library, but I encourage you to go to the GitHub project page, as that will be kept up-to-date and the code below will not.
(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 kv1kv2?1:0 }); keyvals = keyvals.map(function(kv){ return kv.join(colon) }).join(comma); var oneLine = indent+"{"+opad+keyvals+opad+"}"; if (opts.wrap===false || oneLine.lengthkv2?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 kv1kv2?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://stackoverflow.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); ?-1:kv1> )> ?-1:kv1>
回答10:
Thanks a lot @all! Based on the previous answers, here is another variant method providing custom replacement rules as parameter:
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 '' + match + ''; }, 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 ' '; } } ], keys : [ { name : 'Testkey', regex : /("testkey")/, type : 'key', style : function(match){ return '' + match + '
'; } } ], punctuation : { name : 'Punctuation', regex : /([\,\.\}\{\[\]])/, type : 'punctuation', style : function(match){ return '________
'; } } }; 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 '' + match + ''; }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' + match + ''; }else if('function' === typeof p.style){ return p.style(match); } else{ return match; } } } return ('function'===typeof rules.defKey) ? rules.defKey(match) : '' + match + ''; } else { return ('function'===typeof rules.def) ? rules.def(match) : '' + match + ''; } } else { for(i=0;i' + match + ''; }else if('function' === typeof p.style){ return p.style(match); } else{ return match; } } } } }); if(true === pre)str = '' + str + '
'; if(true === code)str = '' + str + '
'; return str; } ;i++){> ;i++){>
回答11:
Douglas Crockford's JSON in JavaScript library will pretty print JSON via the stringify method.
You may also find the answers to this older question useful: How can I pretty-print JSON in (unix) shell script?
回答12:
I ran into an issue today with @Pumbaa80's code. I'm trying to apply JSON syntax highlighting to data that I'm rendering in a Mithril view, so I need to create DOM nodes for everything in the JSON.stringify
output.
I split the really long regex into its component parts as well.
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)
Code in context on Github here
回答13:
It works well:
console.table()
Read more here: https://developer.mozilla.org/pt-BR/docs/Web/API/Console/table
回答14:
If you need this to work in a textarea the accepted solution will not work.
$("#textarea").append(formatJSON(JSON.stringify(jsonobject),true));
function formatJSON(json,textarea) { var nl; if(textarea) { nl = " "; } else { nl = "
"; } var tab = " "; 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; }
回答15:
I recommend using HighlightJS. It uses the same principle as the accepted answer, but works also for many other languages, and has many pre-defined colour schemes. If using RequireJS, you can generate a compatible module with
python3 tools/build.py -tamd json xml
Generation relies on Python3 and Java. Add -n
to generate a non-minified version.
回答16:
This is nice:
https://github.com/mafintosh/json-markup from mafintosh
const jsonMarkup = require('json-markup') const html = jsonMarkup({hello:'world'}) document.querySelector('#myElem').innerHTML = html
HTML
If you're looking for a nice library to prettify json on a web page...
Prism.js is pretty good.
I found using JSON.stringify(obj, undefined, 2) to get the indentation, and then using prism to add a theme was a good approach.
If you're loading in JSON via an ajax call, then you can run one of Prism's utility methods to prettify
For example:
Prism.highlightAll()
回答18:
Here is how you can print without using native function.
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 } } */
回答19:
If you use net.sf.json, you can pretty print as follows (using a 4 space indentation):
JSONObject work = JSONObject.fromObject("{\"hi\":\"there\",\"more\":\"stuff\"}"); log.info("WORK="+work.toString(4));
回答20:
Use Newtonsoft.Json dll. this is work fine in IE and Chrome
put this code in your razor view
if (Model.YourJsonSting!= null) { @JToken.Parse(Model.YourJsonSting).ToString(Formatting.Indented)
}