FlyLatex: A Real Time Collaborative Environment. Some Screen shots of the App

Visit the Github repository of the Free and Open Source FlyLatex app here for more information.

Enjoy!

JSON Pretty Print and JSON Multi level Collapse Code in Javascript and Python

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


// CollapseLib by Daniel Alabi (alabidan.me)
// isPlainObject is part of the jQuery source (I modified the method a little)
/**
* Example use:
* complicated = {"dict1key": {"dict2key": [{"dict3key": {"tell":"me"}}]}}
*
* var dict = CollapseLib.collapseDict(collapse);
* console.log(JSON.stringify(dict, undefined, 2));
*
*/
// todo: fix bug with empty plain object
var CollapseLib = {
/**
*
* @warning allowed types for complexDict : {}, [], JS primitives (int, float, or string)
*
* @param complexDict : a JS object that might have inner JS objects and arrays OR
* a JS array that might have inner JS objects and arrays OR
* @param plainDict : a one-level collapse JS object
*/
// if you have an empty object, just return an empty object
collapseDict : function(complexDict) {
// make plain object to return
var plainDict = {}
, sawComplex = false
, subDict;
if (CollapseLib.isPlainObject(complexDict)) {
// if complexDict is a JS object
sawComplex = false;
for (var complexKey in complexDict) {
// if complexDict[complexKey] is an inner dict
if (CollapseLib.isPlainObject(complexDict[complexKey])) {
if (CollapseLib.isEmptyObject(complexDict[complexKey])) {
return complexDict;
}
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 complexDict is an array
// that contains an inner array or inner plain object
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;
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || typeof obj !== "object" || obj.nodeType) {
return false;
}
try {
// Not own constructor property must be Object
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
}
, isEmptyObject: function(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
return false;
}
}
return true;
}
}

“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):
"""
@param complex_dict : a python dict that might have inner dicts and arrays OR
a python list that might have inner dicts and arrays OR
a python object that's neither list of dict
@return plain_dict : plain dict that has only one level or a plain python object
"""
# make plain dict that you will return
plain_dict = {}
if isinstance(complex_dict, dict):
# if complex_dict is a dict
# loop through the keys of this complex dict
sawComplex = False
for complex_key in complex_dict:
# if complex_dict[complex_key] is a dict
if isinstance(complex_dict[complex_key], dict):
sub_dict = complex_dict[complex_key]
# loop through the keys of this sub_dict
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 not a dict
if isinstance(complex_dict, list):
# if complex_dict is a list
# is complex_dict a list
# that contains a dict or an inner list?
if not isComplexList(complex_dict):
accum = getStrFromList(complex_dict)
plain_dict = accum
else:
# loop through the complex_dict
for i in range(len(complex_dict)):
plain_dict["["+str(i)+"]"] = makeSimpleDict(complex_dict[i])
return makeSimpleDict(plain_dict)
else:
# if neither a list nor a dict
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&quot;,"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;},"player":{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,"mobile":"https://m.youtube.com/details?v=hYB0mn5zh2c&quot;},"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;,"5":"http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,"6":"rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;},"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&quot;,
"data.items.[0].thumbnail.hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;,
"data.items.[0].player.default": "https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,
"data.items.[0].player.mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c&quot;,
"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…&quot;,
"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&quot;,"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;},"player":{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,"mobile":"https://m.youtube.com/details?v=hYB0mn5zh2c&quot;},"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;,"5":"http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,"6":"rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;},"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&quot;,
"hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;
},
"player": {
"default": "https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,
"mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c&quot;
},
"content": {
"1": "rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp",
"5": "http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,
"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

Bed Battles: A Hack’n Jill Hack

During the Hack’n jill Hackathon, I, Phillip Quiza, Allie Riggs, and Jason Wright made an app that disciplines registered users to wake up at pre-determined times during the day by being social and playing games.

The app’s supposed to work like this: You sign up via Facebook on the bed battles website (by allowing the bed battles site have access to your Facebook email only – we honor the privacy of users). You then sign in (still using Facebook) and view your dashboard. Your bed battles dashboard will display some information about your bed battles reputation score (determined from how many previous bed battles you’ve won or lost). The dashboard will also contain information about how much a specific group  (could be a one-person group) of the community of bed battlers owe you for winning your bed battles (if they bet against you) or how much you owe others for winning their bed battles (if you bet against them) and an option to opt out of paying your friends in the bed battles community real money (we’d probably have an option that allows you to pay them in some other way – maybe by buying them ice cream or by just being nice). Using the dashboard, you can also schedule a time you wish to wake up and notify one of your friends that you’ve set up a specific time for both of you to wake up the next day and you want to challenge them to a game on bed battles. Before the challenge, you should be able to, on the bed battles site, negotiate a method of payment or reprisal (or both).

How does the bed battles game work? First, we plan to have more than one game available on bed battles and ideally a user should be able to select which game he/she wants to play with his/her challenger. For the Hack’n jill demo, we made a “shake hard and win” game. It’s a two player game that can be played on a smart phone. The game starts when an alarm (that’s synched with the bed battles site) rings. The user who shakes his/her phone more swiftly and vigorously wins the game. When the game is finished, the information about which user won the bed battle will be posted on the dashboard of both users and will be shared on the twitter and Facebook profile pages of both users. In this way, both users win anyways. They wake up at the same agreed time and play a game together so they get to leave for work (or school) early and also get hyped in the morning ready for work! The result of the challenge between the two users is posted on both Facebook and twitter. Subsequently, the reputation of the winner increases by a certain amount. On the other hand, the reputation of the loser decreases by the same amount. Plus, the loser is notified to pay the user some amount of money (if both money-bet). The “shake hard and win” game is one of many games that users can play. In fact, in the future, we plan to incorporate some multi-player retro games . We also briefly discussed including a “get-to-know-you-more” game that helps players get to know one another better by asking multiple choice questions about players.

Given the time constraints at the Hackathon (8 hours to code), we didn’t finish implementing all the features we wanted to but we’d continue to hone the bed battles
application. A quick listing of what API’s we used: We used the Facebook authentication API for authentication on our site; we used the Facebook Share API and Twitter API to share information about a challenge on the players’ Facebook and twitter profile pages; we used the venmo API to facilitate payments on our sites; and lastly, we used the twilio API to alert players via sms (in the future, we’d add voice sms/call) when the bed battle multi-player game is about to begin.

The Hack’n jill Hackathon was a lot of fun for me and my team! I hope to attend subsequent Hack’n jill Hackathons and I encourage you to do the same. Peace.