Right, let's get started with some basic conventions in the Object Network!

This part in the Object Network series will cover URLs, HTTP headers and some common JSON patterns.

Updated 23/1/12: I changed the URLs in the example to have one of each type.


Here's an example interaction with an Object Network interface:

GET /events/uid-f330a3-4011e.json HTTP/1.1
Host: mobiconfs.com
If-None-Match: "32"
HTTP/1.1 200 OK
Cache-Control: max-age=1800
ETag: "33"
Content-Type: application/json
{ "is": "event",
  "title": "Over the Air 2011",
  "content": "Top Mobile Meetup at Bletchley Park",
  "start": "Fri, 30 Sep 2011 09:00:00 GMT",
  "end":   "Sat,  1 Oct 2011 23:00:00 GMT",
  "location": "http://bletchleypark.org/address.json",
  "attendees": [ "/staff/uid-55d3.json", "uid-06-7d5d" ]

So let's start from the top...



The full event URL is http://mobiconfs.com/events/uid-f330a3-4011e.json, which has a host part, a path prefix, a unique id for this object, and a file type suffix.

Of course, being a URL, none of this is significant from a resource identifying or locating point of view. Any sequence of characters that can be used to find a JSON object will do.

But it will help our routing and debugging to have some handy keywords in the path prefix and it will help our debugging to have a JSON suffix when playing with files.

If we use a JSON database or a relational database, we probably have a UUID or GUID to index and retrieve the object, which can be used in the URL. If we find the object by query, it's possible to pack the query terms into the URL instead.

We avoid actual query strings in the URL because we want to be sure that all caches will work! Also, we don't put auth tokens in the URL, we put them in the headers, as otherwise we fail to identify a real resource with orthogonal access control.

But the most important thing to remember is that the structure of our URLs isn't part of the domain or resource model - it is not significant to clients and we can change it at any time. There are no URL templates or query 'forms' in the Object Network. Our public resource model isn't in the URLs, it's in the JSON formats and the links between objects.


HTTP Headers

There's an integer ETag here, which could increment with every change in object state. Rather store the ETag with the object than calculate the ETag every time from the content, as that could slow you down. ETags are used for both saving network traffic and for change detection. Their use is expected behaviour in the Object Network.

As is the use of Cache-Control; use max-age, not Expires. Always set it, even if you set it to a month or a year, or zero. Get into good habits now and write the code you need, for this and for ETags. In other words, record when your objects change and know how often that happens.

The Content-Type - the Media Type - is application/json. The Object Network is only defined for JSON. This blog page forms the foundation of an Object Network Media Type based on JSON that we'll be defining when we reach rough consensus and running code. Individual object types, such as contact and event, are defined on top of the base Media Type, Microformat-style.

The return code is only used to guide or report on the success of data transfer; it's not used in the Object Network for anything at the domain level. So 200 if transfer succeeded, 303 if it's somewhere else, 304 if it's not changed, 404 if it's not found. We won't need much more than that for now.


JSON Types

Looking inside the JSON, we offer one or more tags asserting what kind of object this is intended to represent - the example above "is" a calendar "event". But clients are free to ignore that and interpret the object or its elements any way they like.

There is a selection of possible types, such as "event", "contact", "user", etc. Plus special tags: "list" and "query", for lists of objects and queries on those lists. For example:

"is": [ "user", "list" ] or "is": [ "contact", "query" ]

An object may be the union of multiple types, such as "is": [ "contact", "event" ], or a 'subclass' with an extra "is" tag and extra fields in the object. If there is only one tag after "is", as in this example, the list brackets are optional.

The semantics, if not the exact syntax, of certain fields in the JSON will usually be declared in the Object Network as being defined in some other standard - in this case iCalendar: "start" and "end" map onto "DTSTART" and "DTEND".

Most fields in the JSON will be defined within the type or format that an object "is", but many will stand alone. For example, "title" above is something that will mean the same in any format, as will "location", and other common fields, such as "created" and "author".

Almost by definition we don't have namespacing in the Object Network. The whole point is to encourage discussion and agreement, not isolation.


JSON Links

Above, "location" indicates a link to another object; just an absolute URL inside a string, which points to an Object Network object on another domain. The "attendees" list has two relative URLs, the first with a full path, giving http://mobiconfs.com/staff/uid-55d3.json.

You can also just put the UID there and let the client put the same relative prefix on and attach ".json" on the end, as in the second attendee above: http://mobiconfs.com/events/uid-06-7d5d.json (maybe that was the organiser, and their URL paths or routes are kept with the events).

It's at least an Object Network convention, and possibly a requirement, that links start with "http://", "/" or "uid-". It may then be useful to add "./" to that list for relative URLs not starting with "uid-". Fully-expanded absolute URLs, starting with "http://", have the advantage of allowing the containing JSON to be directly exported and used independently of its own URL. Absolute URLs can also be detected and rendered as active links in browsers, using a plugin such as JSONView, and in email clients, etc.


List and Link Transparency

A wrapping list isn't only optional for single "is" tags. This rule applies within all Object Network JSON. For example, one email address in a contact needn't be put into a list of one. A corollary of this is that, when pattern matching, a single item will match that item anywhere in a list.

Also, in the Object Network, a link to another object is logically the same as replacing that link with the object itself. In other words, a pattern match will transparently jump over those links and into the linked object's content. It is therefore also valid syntax to directly include, rather than link to, an object.

Links to list objects are also seen as the same as inline lists. For example:

{ .., "email": "uid-111", .. }

where uid-111 is:

{ "is": "list", "list": [ "a@b.com", "c@d.com" ] }

is the same as:

{ .., "email": [ "a@b.com", "c@d.com" ], .. }

This allows lists to be grown outside of their containing object, or reduced back in again. An object can switch at any time between these forms: single-to-list-to-single, link-to-inline-to-link.

There are no nulls or empty lists in the Object Network, or rather, null and empty list are equivalent to non-existent. So:

{ a: [ null ], b: [ null, c ] }

is the same as:

{ b: c }


Linking into the Object Network

Here's one way in: put something like <link rel="object-network" href="/events/uid-f330a3-4011e.json" /> into a Web page to point to the Object Network JSON version of an event, blog post, contact page, etc. Or just have an in-page link, and rely on the client responding correctly to the Media Type.


Next: The Object Network Contact Type.

Previous: Why we should link up our Web APIs.

Join the discussion in the Object Network Google Group!