mark nottingham

Linking in JSON

Friday, 25 November 2011


To be a full-fledged format on the Web, you need to support links – something sorely missing in JSON, which many have noticed lately.

In fact, too many; everybody seems to be piling on with their own take on how a link should look in JSON. Rather than adding to the pile (just yet), I thought I’d look around a bit first.

What am I looking for? Primarily, a way to serialise typed links (as defined by RFC5988, “Web Linking”) into JSON, just like they can be into Atom, HTTP headers and (depending on the HTML5 WG’s mood today), HTML.

5988 isn’t perfect by any stretch (primarily because it was an after-the-fact compromise), but it does sketch out a path for typed links to become a first-class, format-independent part of the Web – as they well should be, since URIs are the most important leg holding up the Web.

My immediate use case is being able to generically pull links out of JSON documents so that I can “walk” an HTTP API, as alluded to previously.

I’m also going in with a bit of caution, because we have at least one proof that getting a generic linking convention to catch on is hard; see XLink.

Now, to the contenders.

JSON-LD: JSON for Linking Data

JSON-LD is a JSON format with a Linked Data (nee: Semantic Web) twist.

  "@context": "",
  "@subject": "",
  "name": "John Lennon",
  "birthday": "10-09",
  "member": ""

Obviously, if you want to fit RDF into JSON, this is what you’d be looking at. Which is great, but most of the developers in the world aren’t (yet) interested in this (no matter how hard the proponents push for it!). It also fails to provide a mapping from 5988; where do I put the link relation type?

I’ve seen a fair bit of advocacy for JSON-LD, especially on Twitter, but in almost every instance, I’ve seen the non-believers push back.

JSON Reference

If JSON-LD is too complex / high-level, its opposite would be JSON Reference, a new-ish Internet-Draft by Chris Zyp and Paul Bryan (who are also working on JSON Schema, JSON Pointer and JSON PATCH, currently being discussed in the APPSAWG).

It’s effectively a one-page spec, where a link looks like:

{ "$ref": "" }

This is effectively static serialisation of a type they’ve defined in JSON Schema, a sort of “meta-schema for links.” I’d previously pushed back on that, because it effectively requires schema support / understanding to get the links out of the document – a real non-starter in many scenarios.

So, I like the concreteness. However, it still lacks any way to talk about relation types, or pop on other metadata; while this could be grafted on separately, the whole point is to have one way to do it.

HAL - Hypertext Application Language

Another attempt is HAL, by Mike Kelly. The JSON portion of his serialisation looks like this:

  "_links": {
    "self": { "href": "/orders" },
    "next": { "href": "/orders?page=2" },
    "search": { "href": "/orders?id={order_id}" }

Here, links are an object whose members are link relations (yay!).

I’m a bit concerned, however, that this object might be a bit awkward to drop into some formats; it relies on _links to identify the structure, so in some places, you’d need a two-level deep object to convey just a simple link.

Also, there doesn’t appear to be any way to link to more than one URI of a given relation type.

What I’d Really Like

I don’t have a specific thing in mind yet, and it’s entirely possible that any of these proposals could be adapted to my needs (or others, I’m sure that they’re out there).

I do have some requirements for consideration, though, along with a few sketches of ideas.


It should be really easy to find links in a document; as discussed above, requiring use of a schema is a non-starter.

This means that there needs to be some sort of marker the link data structure to trigger the link semantics (e.g., how JSON Reference uses “$ref”), and ideally some way to indicate on the document itself that it’s using that convention (to avoid collisions, and help processors find these documents).

JSON Reference does this with a media type parameter;

Content-Type: application/json; profile=

While at a glance that seems reasonable, I have two concerns; first, that JSON itself doesn’t define a profile parameter on the media type (this needs to be done properly), and more seriously, that you can’t declare conformance to multiple such conventions using this mechanism.

For example, if I want to say that my JSON conforms to this convention on links, and another convention about (say) namespaces, I’m out of luck.

I was in Boston recently (for the OpenStack design summit), and during a lull went up to the W3C offices to have lunch. Having this very much on the mind, I asked TimBL for his take, and we sketched out a sort of JSON metadata container, something like:

  "_meta": {
    "json-linking": null,
    "json-namespaces": ["foo", "bar", "baz"]
  // ... rest of doc here

The exact format and content isn’t important here; the idea is having a controlled way (i.e., the keys would probably be in a registry somewhere, and/or URIs) of adding annotations to a JSON document about its contents.

This is not an envelope; it’s just a document metadata container, much like HEAD in HTML. You could put links up there too, I suppose, if it’d help. The important part is that you’d know to look for one of *those* because the media type of the document (or one of its parameters, if we go that way) indicates it’s in use.

What do people think? Is this JSONic enough (whatever that means)?


As mentioned in the discussion of HAL above, the link convention needs to be easy to insert in a format, and not be too convoluted. This probably means an object that’s “marked” with a particular, reserved key, much as JSON Reference does it. A list of links then becomes an array of objects, which seems pretty natural.

Mappable to RFC5988

Again, as discussed, a mapping to RFC5988 is important to me – both so that links can be serialised in various formats, with reasonable fidelity, and so that we can pivot from talking about “RESTful” APIs in terms of URIs to talking about them in terms of formats and link relations, as Roy advocates:

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types).


The object defined needs to be explicitly extensible by the format it’s in, so that link-specific metadata can be added. See the discussion of namespaces in JSON.


A complement to linking in JSON is linking to JSON. While JSON Pointer looks really promising in this regard, and is getting a fair amount of buzz, but I wonder if another mechanism, analogous to xml:id, is necessary.

The use case here is when you want to link to a specific object in a document that may be changing over time; a JSON pointer can be brittle in the face of such change, while a document-unique identifier is much more stable.

This makes a lot of sense in XML, which is primarily a document format. I’m not sure about whether the justification is as strong in JSON, which is primarily a data representation format, but it’s worth talking about.

Just One, Please

Again, there’s not much value in having fifteen ways to serialise a link in JSON; it will end up a pretty ugly mess.


Mike Amundsen said:

You might want to check out my Collection+JSON design; it’s a registered type under the vnd tree right now (

maybe the basic model (collections and items ala Atom/AtomPub) is not what you need but the linking implementation might give you some ideas.

it currently supports:

  • simple links like HTML.A and HTML.IMG
  • parameterized links like HTML.FORM@method=”get”
  • “template” blocks for “write” like HTML.FORM@method=”post”

like Atom/AtomPub, it relies on CRUD-style conventions but, unlike Atom/AtomPub, Collection+JSON is designed to support returning “arbitrary” links/templates in responses to support other actions besides simple CRUD.

Friday, November 25 2011 at 1:50 AM

Mark Baker said:

I dunno, _meta looks pretty close to @context, at least in form and purpose, if not function. I bet that if you tried to standardize _meta while meeting the needs of various producers and consumers, you’ll get even closer.

And IMO, JSON-LD has about as much to do with RDF as does the INI format (since it adds a subject to name/value pairs, making - gasp - triples). I’m using JSON-LD on a project at the moment, with no RDF in sight; triples, yes, but no protocols (serializations) or tooling (libs, databases) that self-identifies as RDF.

Friday, November 25 2011 at 3:22 AM

KevBurnsJr said:

Linking to more than one URI of a given relation type in HAL is easily accomplished using arrays…

{ “_links”: { “tag”: [ {“href”: “/foo”}, {“href”: “/bar”} ] } }

Both formats should be acceptable in a HAL representation.

The service may define which of its rels are always plural and which are always singular. Any client should expect to handle the appropriate form.

There was some discussion about whether all rels should always map to arrays so all rels are always plural. I personally prefer the affordance for singular rels to simplify the usage of pervasive singular rels (particularly rel=self).


is more concise and expressive than


Anyone designing an API could certainly choose to always use the plural link format for all rels in their service if they wish. Singular rels as expressed in the HAL example is an additional affordance.

Friday, November 25 2011 at 5:31 AM said:

I think what Mark Baker meant is that your “_meta” object will end up looking like the “@context” in JSON-LD.

In JSON-LD the context lets you define which elements are treated as IRIs, how terms are expanded to IRIs and so on. It has also built-in support for namespaces by using prefixes.

Let’s look at an example:

{ “@context”: { “homepage”: “”, “@coerce”: { “homepage”: “@iri” } }, “name”: “Markus Lanthaler”, “homepage”: “” }

This (incomplete) JSON-LD document would tell you that there’s a JSON object which has a key “homepage” that represents a homepage according to the FOAF vocabulary - that’s the rel part, isn’t it!? The value of it is “”. The coercion in the context tells a JSON-LD parser that it is an IRI and not just a string.

We are currently also discussing about linking to context documents out-of-band by either a HTTP link header or a media type attribute. That would allow you to convert your existing JSON document into JSON-LD without touching it.

Friday, November 25 2011 at 5:55 AM

Mike Kelly said:

For anyone interested, you can check out hal here:

we also have a google group:!forum/hal-discuss

and the spec is on github:

Kev’s already clarified our approach wrt multiple links against the same rel - if anyone has anything to add to the discussion definitely get on the google group and get involved.

Mark - HAL’s a media type in its own right and its link components aren’t really designed to be mixed in to another type. Instead, it’s intended as a base type to be extended i.e. “built on top of”.

“[in HAL] you’d need a two-level deep object to convey just a simple link” - yep

We discussed a while back that HAL should be tied to the terminology from web linking RFC, this is something on the todo list, definitely let me know if you’re interested in being involved in that effort.

I think HAL satisfies the rest of your criteria. There’s also another important criteria I would add; ‘embed-ability’ - i.e. provide a way to embed another resource’s state, and override the context-URI for contained links and properties. This is something baked into HAL; in fact, this embed mecahnism and the link mechanism are pretty much the entirety of hal+json , in my opinion it’s important to keep things as simple and lean as possible (particularly in the context of JSON).

Keen to hear everyone’s thoughts, my goal make HAL simple and practical for as many people as possible so any criticisms/concerns/feedback are invaluable :)

Friday, November 25 2011 at 7:35 AM said:


Thank you very much for this excellent write-up. In this context, I was wondering what your opinion is on the OData/JSON format [1], as OData is essentially Atom.


Cheers, Michael


Friday, November 25 2011 at 7:36 AM

Colm Divilly said:

Mark, not quite getting the intent of the “json-linking” property, is it just a flag to tell the client that this document contains hyperlinks (in some yet be decided encoding)? Or is it intended to enumerate which properties represent links or something like that?

Of the various efforts you enumerate, the HAL one most takes my fancy. Property names as a rel values is a neat hack. Presumably permitting array values for values would take care of the multiple links for a single rel problem.

Friday, November 25 2011 at 9:38 AM

Mike Kelly said:

I just wrote up an explanation of JSON linking with HAL

Friday, November 25 2011 at 11:00 AM

roberthahn said:

I’m not feeling too comfortable with any of the approaches you outlined, because they all imply the need for some kind of schema that we have to agree on in order to parse the document correctly.

I would rather make a breaking change to JSON and add a new data type called a link. Links would be encoded with pointy brackets, and be used anywhere a string could be used.

Here are 2 quick examples:

{ <> : { “rel”: “contents”, “content-type”: “text/html”, “text”: “Linking in JSON” } }

{ “mnot’s links”: [<>, <>] }

I don’t have a name for this Not Quite JSON variant, but either of these uses would be considered valid. Some may argue that I’m using an implied schema in the first example (but that would be true for all JSON representations), but I would say that the way I’m doing it is more elegant - if you just want a link, you don’t need to invent a schema to represent it - the NQ-JSON parser would know exactly what to do with it. Communicating all of the link details as per RFC5988 is up to you and can be represented by the rest of the natural JSON types (dictionaries, arrays and strings).

Saturday, November 26 2011 at 1:57 AM

Mark Baker said:

Mark - nope, @context has nothing to do with RDF. It just sets the context for interpreting the rest of the information in the JSON, just as _meta appears to do.

AFAICT, JSON-LD’s only built-in feature that comes directly from RDF is @type which is an alias for rdf:type.

Saturday, November 26 2011 at 2:48 AM

Vladimir Razuvaev said:

But linking enables only a subset of hypertext. In HTML you have forms to change state of resource.

Simple linking doesn’t allow this. How would you do “save this blog post as draft” using just links and relations?

Not sure if JSON linking is the only problem which must to be solved to enable full-featured hypertext engine for application state.

Saturday, November 26 2011 at 3:59 AM

Niklas Lindström said:

As Mark Baker says, @context in JSON-LD defines what the keys in the JSON stand for. And that’s the answer to your question about RFC 5988: the keys are the link types.

In the example, the context is external, i.e. linked to. Within it, member is bound to an IRI, and is declared to have its value coerced to a reference. Check out the Person example in the playground for how that looks:

In non-compact form, a reference is explicitly given with an @iri key. But apart from @context, JSON-LD is designed to support aliasing of all special keys. So @iri can be aliased as href or $ref, to get forms similar to the other contenders. Or as said, coercion can be defined to hide away the object construct in favour of a plain string.

Note that while @contexts can be external, and pack some power, they are not intended to be schemas. They map JSON keys to IRIs, optionally declares value coercion (value is either a link or a datatyped literal), and can set default @language and @base (much like HTML).

There is lots of power in JSON-LD, and it would be sad to see non-believers disregard it without a closer look (or perhaps worse, reinvent it). We’re still working out details and rules to make it easy and approachable without sacrificing the richness of dereferenceable terms (for all keys, not just links), datatyping and I18N support that RDF support. Also namespacing (using CURIEs), although most users of JSON-LD use term mappings and/or a default @vocab to make the result JSON (outside of @context) look plain and regular. That’s a key feature of JSON-LD: to support many forms of application-specific JSON while enabling a uniform mechanism (the context) to understand the data in detail.

I have had a great experience creating a plain JSON API upon a rich RDF dataset using JSON-LD, exposing it to consuming application developers with no knowledge of the latter. It enables us to use RDF to coordinate the many providers of data, and give leverage to the domain experts and savvy external consumers to grasp the richness and details, while still providing a very thin and simple JSON surface for casual consumption.

Saturday, November 26 2011 at 5:43 AM

Paul C. Bryan said:

Regarding “_meta”: I like this a lot. A number of metadata conventions have been adopted over time. Standardizing to have a property that contains metadata makes a lot of sense to me. This does raise a question: Suppose the JSON document is not a JSON object? In HTTP, possibly specifying the link to the metadata in a header per RFC 5988?

Regarding: “$ref”: I’m not sure it’s a good fit if the intention is just linking. If the intention is to allow the content to be expressed inline with the possibility of transclusion of another JSON value, it would be a good fit. Otherwise, probably just having an object member with a string containing the URI of the resource being linked to should be sufficient.

Regarding: “profile=…” I agree that to be serious we would need to codify the use of a profile parameter on the media type. I also believe it should support multiple profiles (comma separated?) to allow specifying conformance with various conventions.

Saturday, November 26 2011 at 7:29 AM said:

I’d like to chime in along with all the others suggesting that their own approach to JSON linking is the best!

My approach is a part of the Object Network.

Basically, because the Object Network is based on common, shared, stable types or formats, you simply know that something is a link, just by looking at its tag.

Here’s a simple example, of a calendar event object that links to a contact object for its location, and user objects for its attendees: { “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”: “”, “attendees”: [ “”, .. ]
} So you know to expect links at certain tags, such as “location” and “attendees”, because that what the “event” spec says.

Also, all sensible, data-linking ‘rel’s of RFC5988 can be supported as JSON left-hand-side tag names.

In fact, you can deduce that right-hand-side strings are links when they begin “http://”, etc! Simple JSON-navigating clients can use that without even knowing the formats.

Also, of course, there’s no need for namespacing in the Object Network - in fact it’s actively avoided, following the REST principle of the uniform interface, which means using widely-used and stable types, not ad-hoc ones.

I know you will never agree with this approach, but I felt I should ‘register’ it here for completeness! :-)

Saturday, November 26 2011 at 7:57 AM

James M Snell said:

Some discussion on this over on my G+… and

Sunday, November 27 2011 at 9:21 AM said:

My API (private, but I’m trying to be RESTful with it) offers its links as objects like Client:{Name:”Jon Doe”,HRef:…} so that the UI has something to display without needing to fetch the entire linked object just for one field. So whatever standard is formed, should be able to support arbitrary extra values.

Or I can just use XML, it supports everything that is desirable, but not part of JSON ;-)

Sunday, November 27 2011 at 10:29 AM

Manu Sporny said:

Hi Mark,

I think you may have a number of misconceptions about JSON-LD (based on what you have written above). Others in the comments have pointed out some of these, but let me try to explain what I think they are and why I still think that JSON-LD is a good fit for your use case.

[JSON-LD] smells like RDF, and the use cases are driven from that space. - No, the use cases were not driven from RDF. My goal when putting JSON-LD together was to steer away from the more traditional RDF approaches. Yes, JSON-LD does have a clean round-trip capability to RDF and back, but nobody needs to use that. In fact, at our company, we don’t use SPARQL, a triple store, or any other part of the more traditional RDF stack when working with JSON-LD. We just use JSON-LD, JavaScript and MySQL (and MongoDB) to work with the JSON-LD. It’s a fairly strong movement /away/ from the traditional way of doing things with the Semantic Web. Primarily, we rely on JSON-LD to publish Linked Data (Web objects that point to other Web objects using IRIs). JSON-LD uses the same structure (key-value pairs) that JavaScript developers have become accustomed to - it only changes your workflow as much as you want it to change your workflow. That is, if you don’t want to use the RDF bits of JSON-LD, you don’t have to. If you don’t want to use triples, you don’t have to.

JSON-LD requires a new world view. - This is not true, JSON-LD is designed to be used just like you use JSON key-value pairs today. The people that don’t care about RDF don’t have to bother with RDF and can continue to use the data as just another set of key-value pairs.

It also fails to provide a mapping from 5988; where do I put the link relation type? - There could be an incredibly clear and easy mapping from RFC5988 to JSON-LD. The link relation type goes on the left (as the ‘key’ in the key-value pair). If you’d like to see a clear mapping to 5988, just let me know and it’ll take a few minutes to put something together. All one would have to do is define a context document for RFC 5988 (for example: and then you could do markup like the following: { “@context”: “”, “next”: “” } A very clear mapping for RFC5988 could be created with very little effort. I’ve seen a fair bit of advocacy for JSON-LD … but in almost every instance, I’ve seen the non-believers push back. - Could you link to some of these “non-believer” statements? Non-believers in what, precisely? Linked Data? RDF? Extensibility in JSON? We really haven’t been advocating JSON-LD that heavily since we’re still working out the very last bits of the syntax, but it’s stable enough that people are starting to use it now with some benefit. The best part is that JSON-LD is attracting a community that has been fairly anti-RDF in the past. That is, the JSON-LD community is not the RDF community. There is some overlap, but JSON-LD is showing gains (such as in REST Web Services and document-based databases). Just because there are “non-believers” pushing back doesn’t mean that they understand what they’re pushing back against. At the end of the day, the only thing that matters is that JSON-LD is helping a group of people publish data via Web Services in a way that is fast, inter-operable and that is built on a rock-solid data model. We have a number of stories of developers needing to publish Linked Data that found JSON-LD and immediately saw benefit because it was so much simpler than the more traditional Linked Data technologies.

Again, I may not fully understand your use case - but the proposal you have at the end seems to be re-inventing JSON-LD. “_meta” seems to be doing the same thing as “@context” in JSON-LD. “json-namespaces” seem to be doing exactly what the prefix mechanism does in JSON-LD. “json-linking” seems like it might be doing what the keys in a JSON-LD document do.

So, I think that JSON-LD meets all of your requirements - it can be self-contained, it can be mappable to RFC 5988, it is extensible, and it is anchorable. There are also complete reference implementations for it in JavaScript, C++, Python, and PHP… and a place where you can play around with JSON-LD markup:

Is my reading on your article on-point, or did I miss something?

Monday, November 28 2011 at 6:08 AM

Terris Linenbach said:

This is hilarious! XML sucks so let’s use another crappy untyped format and postpone all of the obvious problems were addressed by DTD when dinosaurs roamed the earth.

Friday, December 30 2011 at 4:08 AM

Markus Tacker said:

Thank you for the compilation of these solutions. I came to the same conclusion-they’re not sufficient.

IMHO there is now way around explicitly describing relations.

To achieve this I’ve created a possible solution by adding a new relation property to JSON-LD data:

Tuesday, January 17 2012 at 11:30 AM said:

Have you seen the “Link Description Object” part of the “JSON Schema” drafts? Current draft: JSON Schema for links:

JSON Schema seems to be getting a bit of traction, and I think the way it uses links is pretty cool. You can either:

1) Use the schema to say that part of the document (e.g. items in the “links” attribute) follows the schema “”. So with the an appropriate schema, the links in this example would be correctly identified: { links: [ {“href”:”…”, “rel”:”…”} ] }

2) Use the schema to define how to extract links from the document. For instance, you could define in the schema that the “author” attribute is a URL representing the author. At that point, a schema-aware system could look at a document that says: { “author”:”…” } and know that there is a link there, with href=”…” and rel=”author”.

Monday, February 20 2012 at 6:27 AM said:

BTW, the JSON schema for the above two examples would be:


{  "$schema":"",  "type":"object",  "links":""


{  "$schema":"",  "type":"object",  "links": [    {      "href":"{author}",      "rel":"author"    }  ]

So at the same time as specifying (or even documenting) the format your data is in, you can also define the rules for extracting links from your documents.

Another cool thing is that the “” schema lets you specify the HTTP method, and also schema for the data that should be sent along with it. So you can say:

{  "href": "...",  "rel": "search",  "method": "GET",  "enctype": "application/x-www-form-urlencoded",  "properties": {    "productName": {"type":"string"},    "productCategory": {"type":"string", "enum":["animal","mineral","vegetable"]}  }

Monday, February 20 2012 at 6:42 AM

Paul Moore said:

In my opinion, we need to take a different approach here.

The above proposals largely try to impart the semantics of their particular media type. What we need is an extensible solution so that the media types can merely document how they extend the base.

I propose the following approach:

i) Establish a JSONised version of the existing link definitions in the standards (RFC5988 and elsewhere), using standard attributes (and document as it’s own media type - application/hypermedia+json?) ii) Document the extensions in the relevant media type specifications

Non-exhaustive proposal for (i):

{ object_vars:.... links: [  {   href: "",   rel: "self edit",   type: "application/vnd.example+json",   title: "Object 1",   .....  },  {   href: "",   rel: "",   type: "application/vnd.example+json",   title: "Related Object 1",   .....  } ]

Expounding on (ii) slightly (and by way of example only) let’s consider

There are various media type specific extensions including “method”, “enctype” & “properties”, to be documented in the relevant media type. The point here is that these extensions have meaning in the context of the “”. They may not have meaning in other media types, and therefore forcing them on others in somewhat dictatorial.

In summary, I think there is scope for a formalisation of a link representation in JSON that is based on the existing standards (RFC5988 and others). Media Types can then extend the base as they see fit. Otherwise, I suspect that if no ‘base’ is agreed, we will be stuck in “battle of media types” with competing semantic requirements.


Wednesday, March 7 2012 at 11:23 AM

Andrei Neculau said:

+1 for JSON hyper-schema

$ref usage described in this article is misunderstood. And while surfing for pros&cons for one or another spec, I don’t see the cons with the JSON hyper-schema.

HAL is pretty peculiar imho. Advertising that links.self.href is better than links.self[0].href gives away an interesting view of the use of relations. ie. self could have use multiple media types (eg. for the sake of the discussion one xml, one json representation), so how do you solve that other than by parsing each of the links? rel, mediaType, method, enctype all have the same importance when deciding which link to use. And beyond that, all the bi-type fields should be minimized. Since I cannot trust that there will be a links.self.href, then I still need to create a “facade” function to check if links.self is an object or an array.

Sunday, April 22 2012 at 11:13 AM

Kavika said:

5988 isn’t perfect by any stretch (primarily because it was an after-the-fact compromise

Can you give some more details about this? I don’t know the history of Atom/AtomPub/5988, and this seems to imply more history than I’ve gotten out of the specs themselves so far. Also don’t know what to google :)

Sunday, April 14 2013 at 8:53 AM