Thursday, October 9, 2008

sharing JSON between web page and server

I've created an App Engine application that uses a field in it's model to store a JSON. This application uses Django and simpleJSON. I wrote my own Javascript framework for App Engine, which I'll try to publish so people can use it. I looked at Prototype and some others but wanted more control since I don't think the browser DOM's are all that hard for simple ajax effects and requests. However, if I must use drag and drop, I will probably enlist the help of a framework. So far I have avoided drag and drop.

The place I want to start out is with JSON. My application is like a project that plays the movie and the movie is the JSON, it is the data.

I started with the example from "Google Maps Hacks" By Rich Gibson, Schuyler Erle

Which was a good placeto start dealing with the Google Maps API and building HTML files that run it. The book is several years old already, so I had to update to the Version 2 maps.

An example of an active Javascript Object on a page with a google map can be seen at igargoyle.com and then view the source for the myObj object.


var myObj = {"photos": [
{"img": "http://igargoyle.com/theman.jpg",
"longitude": "-119.236402821", "latitude": "40.754786911",
"title": "Black Rock City: 2005",
"description": "A Playa Slideshow using Google Maps. Just email this to your friends, and when it loads, it will start playing automatically."},...]}



This is an example of a JSON object being used in HTML script. Notice that it is an object named myObj which contains and array named photos. To retrieve the longitude of the ith element in the array (only the first element is shown above) use


longitude = myObj.photos[i].longitude;


If you have a script to run in the browser or any kind of a states to chose between, if the data is in an array index data structure, each item can be accessed directly by it's index. Arrays are very fast for these sorts of finds, where the number is known. Arrays are not so good if searching for a key needs to be done. If your data fits an array, it will work good as a Javscript object. Think of this object as something that is loaded into the client browser memory when the html page loads. It is then ready to be used to update the page display on user requests and/or timing events. This memory object really only needs the subset of information that the given page may require. No need to put everything from your database on the server in the page. Manipulation can be done in the server side code to send only the data needed by the page. This keeps it small, fast and efficient.

Now that there is a Javascript object in memory on the web page, the web page could have some editing features, to update/change the object. It then needs to be POSTed back to the App Engine server and saved in the datastore. To get the object out of memory, just write it to a hidden (or not hidden) form!

here is a javaScript function that does just that:


function myObj2string() {
var newString =JSON.stringify(myObj);
document.getElementById('JSONbox').value = newString;
}


the JSONbox element should be in the body:



Now that we have captured a Javascript object in a form box, it can be POSTED to the server and stored in Big Table.
This is in the python code



modelEntity.way = request.POST['JSONbox']
db.put(modelEntity)




When the model was built (model.py) for modelEntity, a field for the JSON was included as a TextProperty() which has so far worked well for me.

way = db.TextProperty()


Now that JSONs can be created and stored, to retrieve it and use it, follow these steps.

in django views (python server code):

def play(request, modelEntity_key):
...
newStr = modelEntity.way
...
return respond(request, user, 'viewer', {'ways':newStr})



notice the resonse will call the viewer.html template and pass a context containing newStr which will be called ways. Django passes data to the templates by giving it a context. A context is simply a set of variables and their associated values. A template uses this to populate its variable tags and evaluate its block tags.

putting JSON back into an html page via a Django template:


var myObj = {{ ways }} ;



If the model instance has been passed to the template (eg a context like this: {'modelName':modelEntity} ) the JSON can be pulled directly out of it's model and rendered in the HTML (again this is the Django template):



var myObj = {{ modelName.way }} ;



That should illustrate how easy it is to use JSON. It can be stringified and handled like a string on the server for storage purposes and then used by Django's template and context system where it is rendered in html and then loaded as an object into client memory!