Proposal: Navigation of JSON documents with html-renderer-script link relation

Increasingly, web applications are centered around JSON-based content,
and utilize JavaScript to render JSON to HTML. Such applications
(sometimes called single page applications) frequently employ changes to
the hash portion of the current URL to provide back/forward navigation
and bookmarkability. However, this is largely viewed as an awkward hack,
and is notoriously problematic for search engines (Google has a hash to
query string conversion convention, which is also highly inelegant). We
need support for first class navigation of JSON documents, while still
leveraging HTML rendering technology.

While current methods are ugly, navigating the web via JSON documents
certainly does need not to be at odds with the standard web/URL and
RESTful navigation. Navigation could be visible with plain URLs to
browsers and other user agents (like search engines). Below is a
proposed approach to enable first class JSON document navigation while
the leveraging the current web platform.

Proposal

When a HTML enabled user agent/web browser navigates to a resource and
the server returns a response with a Content-Type of application/json
and a Link header [1] indicating a link relation of
"html-renderer-script", the browser should load the target of the link
relation as a script in the current JavaScript context. Multiple link
relations may be included, and the target scripts should be executed in
the order of the headers. The browser should construct the standard HTML
DOM structure as it would normally do for a blank page or a page with
simple text on it. Once the DOM has been instantiated, the referenced
script(s) should execute. After the JSON document has finished
downloading, the JSON document should be parsed (as with JSON.parse) and
an oncontentload event should fire. The event object must contain a
"content" property that references the parsed JSON value/object. An
example response might look like:

HTTP/1.1 200 OK
Content-Type: application/json
Link: /render.js; rel="html-renderer-script"

{"id":1, "name":"example"}

The standard DOM/JS environment would be created, the render.js script
would be executed (which could be responsible for generating the
appropriate DOM elements to render the data and for user interaction),
and the "contentload" event would fire with the parsed object assigned
to the "content" property of the event property.

A simple example of a renderer script that could used in conjunction
with the example response above:

render.js:
oncontentload = function(event){
  // called for each new JSON doc, render the JSON as HTML
  var content = event.content;
  document.body.innerHTML = 'Identity: ' + content.id + ' Name: ' +
content.name +
     '<a href="' + (content.id + 1) + '">Next</a>'; // include a
navigable link
};

Note that when browsers receive a response with a Content-Type of
application/json, most currently either download with a save dialog or
render it in <pre> element. Browsers can still default to rendering the
JSON in <pre> tag, although the loaded scripts would normally alter the
DOM to provide a custom rendering of the JSON.

When the current page has been loaded via a JSON document, and the
browser navigates to a new URL (whether by back button, forward button,
typing in URL bar, bookmark, clicking on a hyperlink, or window.location
being assigned), the target resource will be downloaded by the browser.
If the response is also application/json and has the same link
relation(s) for "html-renderer-script" as the first document, the
DOM/global object will not be reloaded, but will persist after the JSON
document is loaded. In this case, after the JSON document is fully
downloaded, another oncontentload event will fire, with the new parsed
JSON as the "content" property. Every time the browser navigates to and
loads a new JSON document (with the same renderer scripts) the the
oncontentload event will fire, but the global/DOM environment will
remain in place.

The headers from the JSON document contentload event should be available
via the event.getResponseHeader(headerName) function and the
event.getAllResponseHeaders() function, which act the same as the
corresponding functions on XMLHttpRequest.

Browsers that support loading of scripts in response to
"html-renderer-script" for "application/json" should indicate their
support for this capability by including application/json in their
request Accept header.

Browsers may also fire oncontentprogress events in addition to
oncontentload events if they support progressive loading and parsing of
JSON. The oncontentprogress event should only be fired if the top level
of the JSON document is an array. When an oncontentprogress event fires,
the "content" may be a partial array; containing a subset of the full
document array that will be provided in the final oncontentload event.

Web application authors could leverage browser support for these links
and API to build applications based on JSON content with full
JavaScript-based rendering. The JSON data providers could also include
links (via Link headers) to schemas to inform non-JavaScript user agents
(like search engines) on how to find hyperlinks in the JSON data and
navigate them. JSON Schema [2] provides full support for describing
links and their relations in target JSON data, which can be interpreted
and navigated without JavaScript (but this is beyond the scope of this
proposal). This would mean that JSON represented resources could be
custom rendered, fully integrated into a browser's native navigation,
and even completely crawlable and searchable.

Future enhancements could include browser support for schema-driven
default renderings or JSON style sheets, but this proposal provides a
minimal mechanism that enables an entire class of applications to be
properly URL driven building on existing technology.

[1] http://tools.ietf.org/html/rfc5988
[2] http://tools.ietf.org/html/draft-zyp-json-schema-03

Thanks,
Kris

Received on Friday, 11 February 2011 13:48:58 UTC