EN
JavaScript - how to format json?
7
points
In this article, we're going to have a look at how to write own function to prettify json.
Quick solution:
// ONLINE-RUNNER:browser;
function prettifyJson(json, indent) {
var object = JSON.parse(json);
return JSON.stringify(object, null, indent || '\t');
}
// Usage example:
var uglyJson = '{"name":"John","age": 25,"todos":["Lectures","Classes"]}';
var preetyJson = prettifyJson(uglyJson, ' ');
console.log(preetyJson);
Custom implementation
To format json we need to do 2 steps:
- parse JSON to object,
- render object back to JSON.
To write own object back to JSON renderer function we need to:
- iterate over objects and arrays,
- detect type of object,
- escape unsafe characters like newlines, backslashes, double quote marks, etc.
- join everything together using indents.
Practical example:
// ONLINE-RUNNER:browser;
var TO_STRING = Object.prototype.toString;
function escapeText(text) {
var result = '';
for (var i = 0; i < text.length; ++i) {
var code = text.charCodeAt(i);
switch (code) {
case 0x00: // \0 - NULL
case 0x01: case 0x02: case 0x03: case 0x04:
case 0x05: case 0x06: case 0x07: case 0x08:
continue;
case 0x09: // \t - TABULATOR
result += '\\t';
continue;
case 0x0A: // \n - NEW LINE
result += '\\n';
continue;
case 0x0B: case 0x0C:
continue;
case 0x0D: // \r - CARRIAGE RETURN
result += '\\r';
continue;
case 0x0E: case 0x0F: case 0x10: case 0x11:
case 0x12: case 0x13: case 0x14: case 0x15:
case 0x16: case 0x17: case 0x18: case 0x19:
case 0x1A: case 0x1B: case 0x1C: case 0x1D:
case 0x1E: case 0x1F:
continue;
// allowed characters: 0x20 and 0x21
case 0x22: // " - DOUBLE QUOTATION MARK
result += '\\"';
continue;
// allowed characters: 0x23 - 0x26
case 0x27: // ' - SINGLE QUOTATION MARK
result += '\'';
continue;
// allowed characters: 0x28 - 0x5B
case 0x5C: // \ - BACK SLASH
result += '\\\\';
continue;
default:
result += text[i];
}
}
return result;
}
function getType(object) {
return TO_STRING.call(object);
}
function prettifyArray(array, prefix, indent) {
let result = '[\n';
for (var i = 0; i < array.length; ++i) {
var value = prettifyEntry(array[i], prefix + indent, indent);
if (i > 0) {
result += ',\n'
}
result += prefix + indent + value;
}
return result + '\n' + prefix + ']';
}
function prettifyObject(object, prefix, indent) {
let result = '{\n';
for (var key in object) {
if (object.hasOwnProperty(key)) {
var name = escapeText(key);
var value = prettifyEntry(object[key], prefix + indent, indent);
if (result.length > 2) {
result += ',\n'
}
result += prefix + indent + '"' + name + '": ' + value;
}
}
return result + '\n' + prefix + '}';
}
function prettifyEntry(entry, prefix, indent) {
var type = getType(entry);
switch(type) {
case '[object Array]':
return prettifyArray(entry, prefix, indent);
case '[object Object]':
return prettifyObject(entry, prefix, indent);
case '[object Null]':
return null;
case '[object Boolean]':
case '[object Number]':
case '[object BigInt]':
return entry;
case '[object String]':
return '"' + escapeText(entry) + '"';
default:
throw new Error(type + ' type is not permitted in json.');
}
}
function prettifyJson(json, indent) {
var entry = JSON.parse(json);
return prettifyEntry(entry, '', indent || '\t');
}
// Usage example:
var indent = ' ';
var uglyJson = '{"name":"John","age": 25,"todos":["Lectures","Classes"]}';
var preetyJson = prettifyJson(uglyJson, indent);
console.log(preetyJson);
Note:
undefined
is not valid json token, this is the reasone why is not included in switch cases.