If you are the type of programmer that deals with JSON objects a lot, you are probably familiar with some online programming tools to print out the JSON in a very "pretty" format. These tools not only make dealing with JSON easier and less frustrating but, I must admit, make it more fun too!
A "JSON viewer" app that I use regularly to "pretty-print" complicated JSON objects is at jsonviewer.stack.hu. The app has a very intuitive interface and is thus really easy to use. You can just copy a JSON object to the front page of the app or pull a JSON object from a remote location and then "format" the json. There are many more helpful JSON viewer apps and extensions that are helpful for viewing JSON.
Have you ever had the problem of trying to "pretty-print" your JSON object in your program or app for users to see, or to "collapse" your multi-level JSON object (which might contain arrays in objects and objects of arrays and …) programmatically into one level? I have certainly. Programmers that usually have these problems regularly use or make RESTFUL
API calls — although RESTful "resources" can be transmitted in XML, SOAP, or even YAML, the predominant format on the web is JSON.
"JSON multi-level Collapse" Code in JavaScript and Python
I cooked up the "multi-level collapse JSON" algorithm three days ago because I needed to, given a bunch of streaming JSON objects, collapse each JSON object into the most minimal form and then assemble the JSON objects into a CSV file where each JSON object occupies only one line in the CSV. Yes, my program had to first collapse any JSON object (might contain embedded objects or arrays of objects of arrays of objects of…) into a one-level JSON object without losing any information.
"Multi-level collapse" code in JavaScript
var CollapseLib = {
collapseDict : function(complexDict) {
var plainDict = {}
, sawComplex = false
, subDict;
if (CollapseLib.isPlainObject(complexDict)) {
sawComplex = false;
for (var complexKey in complexDict) {
if (CollapseLib.isPlainObject(complexDict[complexKey])) {
subDict = complexDict[complexKey];
sawComplex = true;
for (var subKey in subDict) {
plainDict[complexKey+"."+subKey] = CollapseLib.collapseDict(subDict[subKey]);
}
} else if (Array.isArray && Array.isArray(complexDict[complexKey])) {
if (!CollapseLib.isComplexArray(complexDict[complexKey])) {
plainDict[complexKey] = CollapseLib.getStrFromArray(complexDict[complexKey]);
} else {
sawComplex = true;
for (var i = 0; i < complexDict[complexKey].length; i++) {
plainDict[complexKey + "[" + i + "]"] = CollapseLib.collapseDict(complexDict[complexKey][i]);
}
}
} else {
plainDict[complexKey] = CollapseLib.collapseDict(complexDict[complexKey]);
}
}
if (sawComplex) {
return CollapseLib.collapseDict(plainDict);
} else {
return plainDict;
}
} else {
if (Array.isArray && Array.isArray(complexDict)) {
plainDict = {};
if (CollapseLib.isComplexArray(complexDict)) {
for (var i = 0; i < complexDict.length; i++) {
plainDict["["+i+"]"] = CollapseLib.collapseDict(complexDict[i]);
}
}
return CollapseLib.collapseDict(plainDict);
} else {
return complexDict.toString();
}
}
}
, isComplexArray : function(arr) {
for (var i = 0; i < arr.length; i++) {
if ((Array.isArray && Array.isArray(arr[i]))
|| CollapseLib.isPlainObject(arr[i])) {
return true;
}
}
return false;
}
, getStrFromArray : function(arr) {
return arr.toString();
}
, isPlainObject: function( obj ) {
var hasOwn = Object.prototype.hasOwnProperty;
if ( !obj || typeof obj !== "object" || obj.nodeType) {
return false;
}
try {
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
return false;
}
var key;
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
}
}
"Multi-level collapse" code in Python
"""
# How to use:
complicated_dict = {"dict1key": {"dict2key": [{"dict3key": {"tell":"me"}}]}}
one_level_dict = makeSimpleDict(complicated_dict)
print one_level_dict
# prints out {'dict1key.dict2key.[0].dict3key.tell': u'me'}
"""
def makeSimpleDict(complex_dict)
plain_dict = {}
if isinstance(complex_dict, dict):
sawComplex = False
for complex_key in complex_dict:
if isinstance(complex_dict[complex_key], dict):
sub_dict = complex_dict[complex_key]
sawComplex = True
for sub_key in sub_dict:
plain_dict[complex_key+"."+sub_key] = makeSimpleDict(sub_dict[sub_key])
elif isinstance(complex_dict[complex_key], list):
if not isComplexList(complex_dict[complex_key]):
plain_dict[complex_key] = getStrFromList(complex_dict[complex_key])
else:
sawComplex = True
for i in range(len(complex_dict[complex_key])):
plain_dict[complex_key+"["+str(i)+"]"] = makeSimpleDict(complex_dict[complex_key][i])
else:
plain_dict[complex_key] = makeSimpleDict(complex_dict[complex_key])
if sawComplex:
return makeSimpleDict(plain_dict)
else:
return plain_dict
else:
if isinstance(complex_dict, list):
if not isComplexList(complex_dict):
accum = getStrFromList(complex_dict)
plain_dict = accum
else:
for i in range(len(complex_dict)):
plain_dict["["+str(i)+"]"] = makeSimpleDict(complex_dict[i])
return makeSimpleDict(plain_dict)
else:
return unicode(complex_dict)
def isComplexList(ls):
for each in ls:
if isinstance(each, dict) or isinstance(each, list):
return True
return False
def getStrFromList(ls):
if isinstance(ls, list):
return ", ".join([unicode(each) for each in ls])
else:
return ls
For example, the output of the "multi-level" algorithm on input the JSON object
{"apiVersion":"2.0","data":{"updated":"2010-01-07T19:58:42.949Z","totalItems":800,"startIndex":1,
"itemsPerPage":1,"items":[{"id":"hYB0mn5zh2c","uploaded":"2007-06-05T22:07:03.000Z",
"updated":"2010-01-07T13:26:50.000Z","uploader":"GoogleDeveloperDay","category":"News",
"title":"Google Developers Day US - Maps API Introduction","description":"Google Maps API Introduction ...",
"tags":["GDD07","GDD07US","Maps"],"thumbnail":{"default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg",
"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg"},
"player":{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c","mobile":"https://m.youtube.com/details?v=hYB0mn5zh2c"},
"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp",
"5":"http://www.youtube.com/v/hYB0mn5zh2c?f...","6":"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp"},
"duration":2840,"aspectRatio":"widescreen","likeCount":171,"rating":4.63,"ratingCount":68,"viewCount":220101,
"favoriteCount":201,"commentCount":22,"status":{"value":"restricted","reason":"limitedSyndication"},
"accessControl":{"syndicate":"allowed","commentVote":"allowed","rate":"allowed","list":"allowed",
"comment":"allowed","embed":"allowed","videoRespond":"moderated"}}]}}
is
{
"apiVersion": "2.0",
"data.updated": "2010-01-07T19:58:42.949Z",
"data.totalItems": "800",
"data.startIndex": "1",
"data.itemsPerPage": "1",
"data.items.[0].id": "hYB0mn5zh2c",
"data.items.[0].uploaded": "2007-06-05T22:07:03.000Z",
"data.items.[0].updated": "2010-01-07T13:26:50.000Z",
"data.items.[0].uploader": "GoogleDeveloperDay",
"data.items.[0].category": "News",
"data.items.[0].title": "Google Developers Day US - Maps API Introduction",
"data.items.[0].description": "Google Maps API Introduction ...",
"data.items.[0].tags": "GDD07,GDD07US,Maps",
"data.items.[0].thumbnail.default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg",
"data.items.[0].thumbnail.hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg",
"data.items.[0].player.default": "https://www.youtube.com/watch?v=hYB0mn5zh2c",
"data.items.[0].player.mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c",
"data.items.[0].content.1": "rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp",
"data.items.[0].content.5": "http://www.youtube.com/v/hYB0mn5zh2c?f...",
"data.items.[0].content.6": "rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp",
"data.items.[0].duration": "2840",
"data.items.[0].aspectRatio": "widescreen",
"data.items.[0].likeCount": "171",
"data.items.[0].rating": "4.63",
"data.items.[0].ratingCount": "68",
"data.items.[0].viewCount": "220101",
"data.items.[0].favoriteCount": "201",
"data.items.[0].commentCount": "22",
"data.items.[0].status.value": "restricted",
"data.items.[0].status.reason": "limitedSyndication",
"data.items.[0].accessControl.syndicate": "allowed",
"data.items.[0].accessControl.commentVote": "allowed",
"data.items.[0].accessControl.rate": "allowed",
"data.items.[0].accessControl.list": "allowed",
"data.items.[0].accessControl.comment": "allowed",
"data.items.[0].accessControl.embed": "allowed",
"data.items.[0].accessControl.videoRespond": "moderated"
}
"Pretty Print" Code in JavaScript
The goal of the "Pretty Print" code is to, given a JSON object (usually used for complicated JSON objects that’s multi-level and really
nested), print the JSON object in a very clear way so that the user sees the embedded arrays, embedded JSON objects, and embedded arrays
in objects and vice versa present in the initial parent object.
So for example, the output of the "pretty print" algorithm on input the JSON object below:
{"apiVersion":"2.0","data":{"updated":"2010-01-07T19:58:42.949Z",
"totalItems":800,"startIndex":1,"itemsPerPage":1,"items":[{"id":"hYB0mn5zh2c",
"uploaded":"2007-06-05T22:07:03.000Z","updated":"2010-01-07T13:26:50.000Z",
"uploader":"GoogleDeveloperDay","category":"News","title":
"Google Developers Day US - Maps API Introduction","description":
"Google Maps API Introduction ...","tags":["GDD07","GDD07US","Maps"],
"thumbnail":{"default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg",
"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg"},"player":
{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c","mobile":
"https://m.youtube.com/details?v=hYB0mn5zh2c"},
"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp",
"5":"http://www.youtube.com/v/hYB0mn5zh2c?f...","6":
"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp"},
"duration":2840,"aspectRatio":"widescreen","likeCount":171,"rating":4.63,
"ratingCount":68,"viewCount":220101,"favoriteCount":201,"commentCount":22,
"status":{"value":"restricted","reason":"limitedSyndication"},
"accessControl":{"syndicate":"allowed","commentVote":"allowed",
"rate":"allowed","list":"allowed","comment":"allowed",
"embed":"allowed","videoRespond":"moderated"}}]}}
is
{
"apiVersion": "2.0",
"data": {
"updated": "2010-01-07T19:58:42.949Z",
"totalItems": 800,
"startIndex": 1,
"itemsPerPage": 1,
"items": [
{
"id": "hYB0mn5zh2c",
"uploaded": "2007-06-05T22:07:03.000Z",
"updated": "2010-01-07T13:26:50.000Z",
"uploader": "GoogleDeveloperDay",
"category": "News",
"title": "Google Developers Day US - Maps API Introduction",
"description": "Google Maps API Introduction ...",
"tags": [
"GDD07",
"GDD07US",
"Maps"
],
"thumbnail": {
"default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg",
"hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg"
},
"player": {
"default": "https://www.youtube.com/watch?v=hYB0mn5zh2c",
"mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c"
},
"content": {
"1": "rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp",
"5": "http://www.youtube.com/v/hYB0mn5zh2c?f...",
"6": "rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp"
},
"duration": 2840,
"aspectRatio": "widescreen",
"likeCount": 171,
"rating": 4.63,
"ratingCount": 68,
"viewCount": 220101,
"favoriteCount": 201,
"commentCount": 22,
"status": {
"value": "restricted",
"reason": "limitedSyndication"
},
"accessControl": {
"syndicate": "allowed",
"commentVote": "allowed",
"rate": "allowed",
"list": "allowed",
"comment": "allowed",
"embed": "allowed",
"videoRespond": "moderated"
}
}
]
}
}
The "pretty print" code in Javascript
It’s just a simple line of JS but not many people know about how to pretty print using an already existing function in JS.
JSON.stringify(objectToPrettyPrint, undefined, 2);
For more information, check out the MDN Docs.