hypermedia - seriously (part 2)

2008-04-27 @ 21:51#

i recently made a couple of posts that focused on the fourth pillar of REST ("hypermedia as the engine of application state"). in one of these posts i made the following assetion:

actually, JSON is not a media-type. it's a serialization type.

subbu called me on that one and he made some very good points. however, i still have some issue with JSON that i want to cover here. and it all has to do with hypermedia.

hypermedia clients

the common web browser is probably the best example of a "hypermedia client." web browsers allow users to request resources and, when available, render hyperlinks within that document. the web browser needs no prior knowledge of the existence or meaning of the hyperlinks before the request is fulfilled by a server. the same holds true for form elements within a resource. servers can fill a client request and send down the proper information to allow the web browser to render an input form with enough details to prompt a user to enter data and send it back to the server for processing. this is (X)HTML and this is hypermedia.

the engine of application state

the ability to follow hyperlinks and send data fields to the server makes it possible for clients to alter the state of the application. in this way, common browsers enable this fourth pillar of REST. actually, it's the web browser's ability properly understand and render (X)HTML documents that makes this possible. it's the content-type (text/html) that contains the rich schema that web browsers can use to render the documents. thus, text/html is not just a media-type, it is a special kind of media-type - a hypermedia-type.

JSON is not a hypermedia-type

JSON is a very good media-type for serializing objects and collections in Javascript. however, it was never intended to act as a full-blown hypermedia type. it lacks a schema that contains definitions for links and forms. in this way, JSON is not able to fulfill the role of supporting the fourth pillar of REST. JSON documents, when sent to the client, cannot act "as the engine of application state." that doesn't mean you can't build a client application that uses JSON as the media-type. lots of them exist. but they are, by nature always going to be one-off applications. applications built for a specific set of interactions. and, if the server changes significantly, the client will break. data will be missing, workflow will no longer function. important steps in the alteration of application state will be skipped.

application/hypermedia+json

to my way of thinking, defining a new media-type - one that fulfills the hypermedia requirements and still uses JSON as the serialization format - is not complicated. this is, essentially, what Atom did for the (non-hypermedia) text/xml media-type. at the core, a schema that defines links and forms withing a JSON resource is needed. much of the work is already done (see XLink and XForms for examples). without sweating the small stuff (and there's lots of small stuff), the following JSON snippets should point the way to a possible hypermedia format (please pardon my sloppy JSON here):

{"linK" :
  {
    "href" : "/users/",
    "title" : "user list"
  }
}

{"links" :
  [
    {
      "href" : "/users/",
      "title" : "user list"
    },
    {
      "href" : "/users/?recent",
      "title" : "new users"
    },
    {
      "href" : "/users/?admin",
      "title" : "admin users"
    } 
  ]
}

{"input":
  {
    "type":"single-line",
    "name":"user-name",
    "validator":"^[\w]{5,25}$"
  }
}

{"form" :
  {
    "href" : "/comments/",
    "method" : "post",
    "accept" : "text/xml"
  }
  "inputs" :
  [
    {
      "type" : "single-line",
      "name" : "user-name",
      "validator" : "^[\w]{5,25}$"
    },
    {
      "type" : "single-line",
      "name" : "email",
      "validator" : "\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b"
    },
    {
      "type" : "multi-line",
      "name" : "body",
      "validator" : "^.{1,500}$"
    }
  ]
}

by establishing a well-defined schema for handling hypermedia, JSON can become a full-fledged format for controlling application state. this would make it possible for JSON-enabled clients to handle changes in workflow and data-models without having to re-write the client code.

code