No Mod Required

Archive for the 'json' Category

JSON Feeds For Fun and Profit Part 3- wherein Eval() kind of bums me out

(and several months later I finish my little JSON series…)

So far my exploration of JSON has been a fun-filled walk in the park. Moonbeams and rainbows. All that.

This last post on the subject is slightly less cool as I get into one of the least attractive components of the whole JSON thing- the use of eval() to transform a text response into a proper JavaScript object. The use of eval() is one of the reasons I originally was a little shy about using JSON. Why? eval() is slow and I try to stay away from slow if at all possible. That and the idea of eval()-ing code from some third party makes me wary.

Obviously, if you’re using a callback, or are just using a built in object reference which inserts itself into memory as soon as the script is attached a script to a page, eval() won’t come up, but sometimes there’s no other option but to ingest the JSON feed as plain text and eval() it into Object-hood. The feed I was helping out a co-worker with last week (AKA back in August when I originally wrote this) which spurred on this very series of posts was one such feed. It looked something like this example cribbed from JSON.org:

{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}

As you can see, if you attach that script to the document using a script tag, there’s absolutely no way to get anything out of it. No amount of poking at it will communicate the contents of that file to the rest of the scripts on the page. There’s no reference in memory and there’s no way to create one. It has to be ingested using an XMLHttpRequest and eval() has to bring it into life. Since it uses XHR and not a dynamic script tag, that means a local pass-though script on the server side is needed to get around cross site scripting constraints. In other words, we’re looking at a big pile of “why bother?” For my money, if you have to go through these steps, then plain old XML makes more sense.

Anyway, if you have to use JSON and the only option is a response structured like the above, then the following is one way to handle it.

First, an example “tag cloud” hacked together with a raw JSON tag feed from del.icio.us:

Now some code:

<script type="text/javascript">
function ajaj(json_doc,callback) {
  //ajaJ? get it? so clever.
  //create a cross browser XMLHttpRequest object
  //let's do this
  	http= new function() {
  	var xmlhttp;
  	try {
  	//start with the standard
 	 xmlhttp = new XMLHttpRequest();
 	}
 	catch(e) 
  	{
 	 //do the IE thing if the above fails
	  //IE deserves some props since they actually created 
 	 //the whole XMLHttp thing
  	xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } 
  return xmlhttp;
  };
  //is it okay to try this?
  if((http.readyState==0)||(http.readyState==4))
  {
  //I do this in a try/catch since  there's 
  //always a chance of some 
  //sort of data error and I want the 
  //possibility of using a fallback function
  //if there is some sort of internet hiccup. 
  //I also hate showing errors to the user
  //In this case I could just drop it since
  //I'm not doing anything special here, but 
  //I'm not about to reinvent the wheel
  //since this is more about JSON 
  //than the way I use XMLHttpRequest 
  try 
  {
  //open the connection
  http.open("GET", json_doc, true);
  //set up a function to handle the response
  http.onreadystatechange = function handle_http_response() 
  {
  //I take no chances.
  //you can have have readyState of 4, a status 
  //of 200 and still run into trouble
  //I want to know all my ducks are in a row :) 
//I'm all belt and suspenders 
  if ((http.readyState == 4)&&(http.status==200)&&(http.responseText!=null)) 
  { 
//First I create an empty object, the same structure as the regular Delicious JSON feed
//I like the structure of their feeds so I'm replicating them here.
  Delicious = {}
  //Use eval to bring the response into the Object
//Again, I'm using Delicious' own Delicious.tags structure
  Delicious.tags=eval('('+http.responseText+')');
  //we've got this handy object now that we've done our eval
  //we pass it as an argument to the callback function
  callback(Delicious);
  }
  }
  }
  catch(e) 
  {
  //we could do some stuff here to handle errors
  }
  //let's put an end to this transaction
  http.send(null);
  }
  }
  //this is the callback function
  function delicious_me(Delicious) {
  //this is an object functioning as 
  //an associative array
  //not a proper indexed array typical of most JavaScript
  //so we use a for... in loop
  //which loops through all the members of the array by named reference
  for (var i in Delicious.tags) {
  //inside the loop i will refer to the property name
  //tags[i] will return the value
  //BTW, the tag cloud is a total hack. 
  //I should do some better math here, 
  //but like the XHR stuff above 
   //this isn't really about a tag cloud...
  document.getElementById("delicious").innerHTML+="<a href='http://del.icio.us/rob_react/"+i+"' style='font-size:"+Delicious.tags[i]/2+"px;line-height:"+Delicious.tags[i]/2+"px;'>"+i+"</a>\n";
  } 
  }

The interesting bit, at least in the scope of this article, is this where we use the eval method to pull the responseText into the Delicious and pass it to the callback function.

Delicious.tags=eval('('+http.responseText+')');
callback(Delicious);

Nothing groundbreaking there and, honestly, not much for me to get excited about. I just don’t like the use of eval and would go to great lengths to avoid using it. That said, if you’re in a situation where a raw JSON feed is all you’ve got to work with, this is a way out of the jam.

For my next, and final entry in this I’ll use this handy JSON parser for the safe alternative to eval(). That should make me a little happier than this example.

JSON Feeds For Fun and Profit Part 2 - Callbacks with Twitter

In my first exploration of the JSON data interchange format, I used it in its most basic way possible. I attached a script (from delicious) to a page and simply used the built-in object created by their implementation to generate an unordered list of my recent del.icio.us posts. While it showed how easy it is to use the O, a handy, structured, Javascript Object, provided by JSON, it didn’t really illustrate how to manipulate the page with new data after page load. That is, after all, a very now thing to do, so it’s kind of important. This article will examine how to dynamically load a JSON feed and how to get data out into a usable form using a callback.

While one can load JSON using XMLHttpRequests, the real benefit of JSON is to be able to load data from a third party without worrying about the browser security model and without having to rely on a local pass through file. So, we’re going to load the data without XHR in this example. Instead we’re going to load it using dynamic script tags.

Here’s the function I’m using in my example:

function twitter_me() {
   var twitter_JSON = document.createElement("script");
   twitter_JSON.type="text/javascript"
   twitter_JSON.src="http://twitter.com/statuses/user_timeline/rob_react.json?callback=twitter_callback&count=10"
   document.getElementsByTagName("head")[0].appendChild(twitter_JSON);
}

First I create a new script element in the document, then I set the type and source. The source is the interesting part. As you can see, after the URL for the JSON document representing my twitter updates, I append a query string. The first argument for that query string (callback=twitter_callback) is where the magic happens. There I’m defining the function that will be called when the script is attached to the document. To see what happens compare the first few characters of the JSON script called with and without the callback.

Here it is, as referenced in the above code

twitter_callback([{"source":"web","text":"426 queries in 107.66 milliseconds. drupal is teh awesome",

and called without the callback (but with the count, so the data structure returned is the same)

[{"source":"web","text":"426 queries in 107.66 milliseconds. drupal is teh awesome",

Notice the function referenced in the first example. Right there, as soon as the JSON document is loaded, JavaScript executing the callback function with the JSON object as an argument. I'm a JavaScript geek and all, so I'm biased... but that's just plain cool.

So what happens next, you ask? Well, since I defined a function called twitter_callback, that function is run and I'm able to do all sorts of cool things with the provided object. Here's the function in all its glory:


function twitter_callback(twit) {

 //this is the div I'm writing the content to
 var t_div = document.getElementById("twitter");

//these are some other variables, mostly
 //placeholders so that the code is a little clearer
 var who,what,when,icon, bgcolor

//start the ul
 t_div.innerHTML = "<ul>"

   //loop through the twit object
   for (i=0;i<twit.length;i++) {

   //Look at me use the JavaScript modulus operator to do even/odd rows.
   if(i % 2) {
      bgcolor="#efefef"
   } else {
      bgcolor="#ddd"
   }

   //Right here, I've broken out the separate bits of the string into placeholder variables
   //so you can more easily see the dot notation and array indices in place
   //once you figure out the structure it's dead easy to reference data in an Object
   icon=twit[i].user.profile_image_url;
   who=twit[i].user.name;
   what=twit[i].text;
   when=twit[i].created_at.substr(0,19);

   //and here I mash it all up into a fancy li
   t_div.innerHTML +="<li style=’background:"+bgcolor+" url("+icon+") no-repeat’><strong>"+who+"</strong>: "+what+" ("+when+" GMT) </li>"
   }
  //and close the UL
  t_div.innerHTML += "</ul>"
}

Here it is in action (be patient, Twitter can be slow):

Call me crazy, but that’s something like 75% away from being a widget and there are no cross domain concerns to deal with so it could easily be spread far and wide. There’s a lot to like right there :)

That’s it for this time. Feel free to ping me with questions or comments.

Next up, as I mentioned, one can load JSON via XMLHttpRequest, so I’ll be building an example that does just that. There’s a wrinkle tossed in with that technique that will make things, if not tougher, a little less cool (eval(), I’m looking in your direction.) More on that when I put it all together.

JSON Feeds For Fun and Profit, Part One- Del.icio.us makes it easy

Confession time: I’ve never actually worked with a JSON feed.

No, really.

I know what you’re thinking… Yes, you’re right. I’ve built a bunch of Ajax-y components and one full blown application over the past two years.

No, in light of that it doesn’t make any sense that I haven’t used JSON before.

Anyway, I’ve been helping out one of our developers at work with My Big Javascript Brain™ and I’ve had to mess about with JSON a little bit. She’s ostensibly a Java developer, but she’s shown a willingness to help out wherever she can (thereby learning a bunch of other web technologies,) so this week she’s been tasked with creating a JSON fed Google widget. This has been interesting for me, as I’ve had to guess a lot and leap at solutions at every turn to try to help her (since I have no practical experience with the acronym myself.) The good thing is I’ve actually been helpful. Apparently I’ve soaked up enough about JSON through osmosis or something, because when that feeble amount was blended with my regular JS knowledge I was actually able to piece together some of what was going on. Go me.

Anyway, to actually know what I’m doing the next time, I’ve decided to play around with some feeds right here and write up what I discover to help solidify my own knowledge and to help out anyone else who might be wondering about the magical world of JSON feeds.

Did I mention that they were magical? They are. They’re made of pixie dust and rainbows.

Yes, I’ve gone slightly off the rails… ignore that last bit.

To start with, I decided to use the handy feed from one of my favorite web twenty web sites, del.icio.us. Not surprisingly, since del.icio.us kicks all kinds of ass, they make it dead easy to use JSON feeds. All it takes is attaching the script generated at http://del.icio.us/feeds/json/user_name to a document and a Delicious JavaScript object is automatically created- full of all sorts of social bookmarking goodness. Notably a posts array which contains all of the selected user’s posts.

You can read their concise documentation here. They have a nifty sample as well.

Here’s the example I whipped up. This grabs the last 15 bookmarks from my account, takes the link, description and tags and drops them all into a regular old unordered list*.

Here’s the feed itself. As you can see it contains a simple test to see if the Object already exists, an object definition and then an array populated with all of the post data. Pretty straightforward, really.

The following code sample shows how I did it. My comments are inline and in blue.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>JSON part 1</title>

<!--Seriously. This is all it takes to get the object into your document. 
That's really cool, right? I think so-->
<script type="text/javascript" src="http://del.icio.us/feeds/json/rob_react"></script>
<script type="text/javascript">
window.onload = function() {

//this is the built in delicious object. 
//the array posts has all the stuff we're looking for. 
//let's make a quick reference to it
var del = Delicious.posts;
var d_div = document.getElementById("delicious");

// create a placeholder for the link
var the_link=""

//****As a note, I've found writing out innerHTML 
//****to be faster, so I use it. 
//****I actually prefer the elegance of JavaScript's 
//****DOM based node creation and manipulation methods.
//**** but speed roolz, so I play with strings
//**** sometimes this stuff can get really confusing, 
//**** though, so I'll fall back and use
//**** the DOM stuff anyway. 
//**** Anyway, back to the script...

//write the beginning of the <UL>
d_div.innerHTML = "<ul>"

//loop through every element in the Delicious.posts object and do stuff
for (i=0;i<del.length;i++) {

//look at me, I'm doing stuff!
//clear the placeholder for the link
the_link="";

//  add in the opening of the LI and the opening of the anchor
// add a reference to the u (url) of the i member of the del array
// and the d (description) of the same memberr
the_link ="<li><a href='"+del[i].u+"'>"+del[i].d+"</a>";

//are there tags? is there a tags array of the i member?
if (del[i].t) {

//if so lets write them out
the_link +=" <em>tags:</em> "

//loop through all the mambers of the t (tag) array
for (j=0;j<del[i].t.length;j++) {

//and build another link
//here I'm using the simple, but powerful URL scheme
//that delicious uses to nice effect
//by dropping the the tag onto the end of my delicious url
//I'm easily building out links to my tags
//they use a logical, transparent url scheme which makes 
//it crazy easy to navigate both as a user and as a programmer
//go delicious go.
the_link +="[ <a href='http://del.icio.us/rob_react/"+del[i].t[j]+"'>"+del[i].t[j] +"</a> ]" 
}
}

//close out the li
the_link += "</li>"

//pop that link and li into the div
d_div.innerHTML += the_link
}

 //once the loop is done, close the ul
d_div.innerHTML += "</ul>"

//and that's that. like I said, pure magic.
}
</script>
<style type="text/css">

/*I've got style*/
body {
color:#666;

/*by the way, shorthand is your friend!*/
font: .825em/1.8em Verdana, Arial, Helvetica, sans-serif;
}
em {
color:green;
margin-left:10px;
}
</style>
</head>
<body>
<div id="delicious">
</div>
</body>
</html>

And that’s that- a run-through of the simplest possible usage of a JSON feed (at least in terms of extracting the data.) Next time (which should be soon) I’ll look at different methods for getting dynamic data out of JSON. Oh, the fun we’ll have.

(part 2 of this series | part 3 of this series)

*The note is also available- I’ll use that in my next example.