2007-02-11

JSONP and Spreadsheets

A year has passed since I wrote about the merits of JSONP, and since then, services have slowly started using it, allowing you to use your data from web pages anywhere in contexts outside of the site of the services in question. Adoption is not very rapid, but every service that adopts it and does it well is a great win for the online community (and, I argue, the services themselves), since they are increasing the leverage of web programmers all over the world to a great extent.

Possibly even more so than javascript libraries and frameworks on offer; at the heart of JSONP lies a core of very lightly wrapped, highly concentrated raw data served in the most easily digestable format possible for a javascript programmer. It's just the matter of pointing a script tag at the data, and the data comes to your code, an HTTP request and a function call later. You just name the callback and get to do whatever it is you want to do with the data. (Yes. It really is that simple.)

The topic of this post will be spreadsheets, as spreadsheets is a very useful and low-barriers-to-entry way to access and maintain organizing structured data, the bread and wine of web applications, widgets, aggregation services and other tools and accessories you live and breathe on the web. Every one processes data of some sort, and most have a need to get it from somewhere. And I think online spreadsheets have lots of merit here, addressing a sore need in a very good manner.

No online spreadsheet that I am aware of supports JSONP natively today, though you can coax at least Google Spreadsheets and EditGrid into "sort of" supporting it. In the Google case you get valid and a letter correct JSONP feed, which is however not JSONP in spirit, whereas with EditGrid you get as good a spiritual match as you care for, but no URL configurable javascript callback name. So neither is really there yet, but I'll discuss how even this is already enough to be useful, after a fashion.

Google Spreadsheets

Let's start with Google, as there is less to say about that. Nowhere in their interface is there an actual JSONP (or JSON) option to pick, but you can ask its ATOM feed formatter to reformat its data as (surface) JSONP and it will happily comply. The question, however, when devising an export format, is always "how would my data best be expressed for its target domain?", which, in the case of JSONP, is javascript. And since javascript has multidimensional arrays, which is what a spreadsheet gives a visual face to, and ATOM does not, the outcome when you reformat the ATOM feed as JSONP is, shall we say, suboptimal.

You reformat a Google Spreadsheets ATOM feed to JSONP by appending the URL query parameter ?alt=json-in-script at the end of its URL, and, making it interactable client-configured JSONP, Google accepts the additional parameter callback, naming our callback, and supplies it with the gobbeldegok that came out of the transformation. The ATOM feed is limited to single sheet output, and given all of these constraints, here is what (reindention for humans by me; the original feed is even less legible -- not to mention the horrible URL) comes out of this example spreadsheet:
/Sheet1\      /Sheet2
A:1 B:1 C:1       b:1    
A:2 B:2 C:2   a:2 b:2 c:2
A:3 B:3 C:3   a:3     c:3
In summary, it chewed off A:1, drenched the place with huge id URLs, links, pointers to schemas and other junk invented out of nowhere, added some useful metadata about the file and munged together cells into not separately addressable entities (an example of which being row 2, which came out as "A:2" and "B:1: B:2, C:1: C:2"). Still, even given this gooey mess of things, fine hackers such as David Huynh manage to craft gems atop it. I again warmly recommend Exhibit. Expect upcoming and more in-depth articles about it here, as I have amassed a large backlog of great hacks with it recently. It is a very hackable visualization engine indeed.

EditGrid

EditGrid does lots of things right, and in great style. They even care about making your URLs look good. Their developer interfaces are paid equal amounts of love and attention as are their user interfaces, which in this case is great praise for both.

The data you commit to an EditGrid spreadsheet not just sits there, but bends to your will and comes out in whichever data format you care enough about to craft or look up a conversion template for -- which is done on the fly by applying XSLT templates server side to the XML format they export to. To finish it off, all URLs are legible, short and converting to a different format using either of the built-in defaults or your own custom formats is a simple matter of changing the extension. Here is our example, again, at http://www.editgrid.com/user/ecmanaut/example. The live URL allows anyone a spreadsheet interface to the documet, and the author and those he chooses to share editing priviges with, the option of editing it. Watch the other permalinks below and feel the warm fuzzies inside:

FormatOutput
XML.xml
HTML.html
CSV.csv
PDF.pdf
Excel.xls
OpenDocument.ods
OpenOffice 1.x.sxc
Gnumeric.gnumeric
TeX source.tex

I took some time to hack up a few useful variants on JSON and JSONP formats of the data for myself (and indeed others; take your picks -- and should you feel like extending them further, I recommend working off the last one, which plays best on the strengths of XSLT, .null.cells.json). It's not full-blown JSONP, of course; you can't configure the callback name from the URL the way you should be able to (which becomes useful the instant you import more than one spreadsheet), but this is as close as we get without the interactive step.

I have organized the formats and the XSL templates by their properties; a few are standards compliant JSONP, following the JSON definition, some are even more size conservative and employ the short form used by javascript to define sparse arrays where there are empty cells. Those that are legal and interoperable JSON(P) (not all JSON consumers are javascript!) are tinted greenish in the table, the rest slightly rougeishly blushing.

Empty cells become ""Empty cells omitted
Plain JSON.xsl .json
{"workbook":[
{/*...*/},
{"name":"Sheet2","sheet":[
[{},{"type":"string","input":"b:1","value":"b:1","content":"b:1"},{}],
/*...*/]}
}
.xsl .null.json
{"workbook":[
{[/*...*/]},
{"name":"Sheet2","sheet":[
[,{"type":"string","input":"b:1","value":"b:1","content":"b:1"},],
/*...*/]}
}
JSONP, data only.xsl .data.jsonp
editgridCallback({"workbook":[
{"name":"Sheet1","sheet":[
["A:1","B:1","C:1"],
["A:2","B:2","C:2"],
["A:3","B:3","C:3"]]},
{"name":"Sheet2","sheet":[
["","b:1",""],
["a:2","b:2","c:2"],
["a:3","","c:3"]]}
})
.xsl .null.data.jsonp
editgridCallback({"workbook":[
{"name":"Sheet1","sheet":[
["A:1","B:1","C:1"],
["A:2","B:2","C:2"],
["A:3","B:3","C:3"]]},
{"name":"Sheet2","sheet":[
[,"b:1",],
["a:2","b:2","c:2"],
["a:3",,"c:3"]]}
})
JSONP, all properties.xsl .cells.jsonp
editgridCallback({"workbook":[
{/*...*/},
{"name":"Sheet2","sheet":[
[{"type":"","input":"","value":"","content":""},/*...*/],
[{"type":"string","input":"a:2","value":"a:2","content":"a:2"},/*...*/],
[/*...*/]]}
})
.xsl .null.cells.jsonp
editgridCallback({"workbook":[
{/*...*/},
{"name":"Sheet2","sheet":[
[,{"type":"string","input":"b:1","value":"b:1","content":"b:1"},],
/*...*/]}
})
Exhibit JSONP.xsl .exhibit.jsonp
editgridCallback({"items":[
/*...*/
{"type":"Sheet2","":"a:3","b:1":"","":"c:3"}]
})
.xsl .null.exhibit.jsonp
editgridCallback({"items":[
/*...*/
{"type":"Sheet2","":"a:3","":"c:3"}]
})

I'll get back about how to use those Exhibit JSONP to do great things. This post is mostly for reducing my backlog about things to blog to get things out where people can play with and work their own magic with them.

11 comments:

  1. Are those XSL available? If yes where?

    ReplyDelete
  2. They are, either by saving my live stylesheets pointed to by the .xsl links above, or by picking them up from my subversion repository.

    ReplyDelete
  3. Johan: In case you do not know, JSONP is now available for EditGrid see https://wiki.editgrid.com/wiki/Advanced_Features/JSONP. Also, is there a way to allow for multiple items in each cell (for example to have two items for two categories)? When I try to separate the multiple items in an EditGrid cell they are still treated as one item by Exhibit using JSONP. Otherwise the xsl stylesheets your provided are working great for use with Exhibit. Thanks for all your hard work and sharing your knowledge.

    ReplyDelete
  4. They actually even had the good judgment of running it by me (just prior to releasing it), allowing me to help them catch a few flaws and a security hole they quickly patched up, so I'm aware of the, finally native, great feature.

    Re: multiple data items in a single cell for Exhibit, I suggest using a convention of yours of some kind to separate values from one another -- semicolon, for instance, if that is a character that won't show up in items themselves, and craft an ex:converter function which splits the values of that cell on this separator, before returning it to Exhibit.

    If you don't manage to work out how to do that on your own, feel free to give a URL to an exhibit where you have data on that format, and I can probably help you tweak it.

    ReplyDelete
  5. Johan:

    Thank you for your help. I've tried numerous times to do an ex:converter function without success. The multiple data items are separated in cells by a semicolon. The URL of my Exhibit is at http://www.swingingsammy.com/myerstimeline/myerstimeline20C.html. Everything is working but the lack of separator. I have items in the category and era facets that need separating. Any tweaking or guidance would be greatly appreciated.

    ReplyDelete
  6. Try making your <link rel="exhibit/data"> read <link rel="exhibit/data" ex:converter="convert"> and add a function

    function convert( json ) {
    var items = json.items;
    for (var i = 0; i < items.length; i++) {
    item.category = item.category.split("; ");
    }
    return { items:items };
    }


    somewhere in the page, and it'll probably work better.

    ReplyDelete
  7. (Oops; the for loop body should have a line reading var item = items[i]; first.)

    ReplyDelete
  8. Johan:

    Thank you for the help with the code. With a few minor tweaks, it works great and I have finally connected an EditGrid page with multiple items in a cell with an Exhibit page.

    ReplyDelete
  9. can we get the actual stylesheets?

    ReplyDelete
  10. Sure; I didn't notice when editgrid stopped publishing the .xsl links in the chart above to non-logged-in users. Here are the top left two examples, for now (I'm just on the go, so I'll get back to the other later):

    json.xsl - http://gist.github.com/464789
    data.jsonp.xsl - http://gist.github.com/464789

    ReplyDelete

Limited HTML (such as <b>, <i>, <a>) is supported. (All comments are moderated by me amd rel=nofollow gets added to links -- to deter and weed out monetized spam.)

I would prefer not to have to do this as much as you do. Comments straying too far off the post topic often lost due to attention dilution.

Note: Only a member of this blog may post a comment.