JSON:API 1.0

June 04, 2015
API, JSON:API

Yehuda Katz wrote the first draft of the JSON:API specification in May 2013 after hammering out the details in a long discussion with Steve Klabnik at RailsConf. JSON:API began as a codification of the shared expectations of a single server library for Rails, ActiveModel::Serializers, and a single JavaScript client library, Ember Data. (As a bit of prehistory, I gave a talk about these shared expectations at the first EmberCamp in February 2013).

Yehuda and Steve saw the value of separating these expectations into a formal specification that any client or server library could implement. Critically, the specification was encouraged to evolve in parallel, rather than in lockstep, with the original implementations. As a result, JSON:API has been influenced by developers both in and outside the original Ember and Rails communities from which it originated, which has undoubtedly resulted in a stronger spec with broader appeal.

After two years, four release candidates, hundreds of pull requests and issues, and countless hours of discussion, the JSON:API specification has finally reached 1.0.

Now that JSON:API is stable and committed to allowing only additive changes, it's poised to reach its full potential. At this unique time in the life of the specification, it seems appropriate to look both back at the journey to 1.0 and forward to the road ahead. But first a look at what makes JSON:API unique...

An Ambitious Specification

JSON:API is ambitious in purpose and scope: it defines both a media type (application/vnd.api+json) and rules for the usage of HTTP to fetch and modify resources represented by that media type. In this way JSON:API is similar to the Collection+JSON specification, but it has an even broader scope.

By standardizing so many of the decisions around designing and building an API, JSON:API allows developers to focus on the design of their applications.

Goals

So what kind of API will you build by following JSON:API? The spec states its goals in this way:

JSON:API is designed to minimize both the number of requests and the amount of data transmitted between clients and servers. This efficiency is achieved without compromising readability, flexibility, or discoverability.

These goals are apparent throughout the design of the spec. Features such as compound documents, sparse fieldsets, and multi-field sorting allow clients to request exactly the data they need from a server and nothing more.

For instance, let's imagine an API for a blog that exposes articles, comments, and people as resources. A client might make the following request:

1
GET /articles?include=comments,author&fields[people]=first-name,last-name&sort=-date

The above request will fetch all articles as well as their associated comments and authors. People resources (authors in this case) will only be returned with their first and last names. The article collection will be sorted by date, most recent first. The server will either return all the results together in a single response document, or it may paginate them. JSON:API also specifies how pagination links must be returned so that any compliant client will understand them.

A Focus on Hypermedia

JSON:API has really benefited from Steve Klabnik's continued involvement. Steve is not only a standards junkie and hypermedia proponent - he is also literally writing the book on hypermedia APIs.

Thanks to Steve's influence, it's possible to build hypermedia APIs with JSON:API. Links can be added throughout JSON:API documents to specify canonical URLs for resources and their associated relationships. Clients can "crawl" links in an API just as your browser crawls links in HTML. By eliminating the need to hard-code URLs (or the logic to derive them), clients and servers become more loosely coupled and can more easily evolve.

Why JSON:API?

The Anti-Bikeshedding Weapon

JSON:API has gained entry to many organizations through its strong and consistent conventions that span almost every aspect of a "RESTful" API. Once a team starts to design an API, they often realize just how little guidance is provided by REST's constraints. Rather than bikeshedding for hours over minor API design details, many teams have turned to JSON:API for guidance.

The base JSON:API specification provides conventions for:

  • representing singular resources vs. resource collections
  • identifying resources, including heterogenous (mixed type) resources
  • including primary and related resources in a single compound document
  • representing relationships between resources
  • hypermedia links for resources, relationships, paginated collections, and more
  • fetching, creating, updating, and deleting resources and relationships
  • sparse fieldsets (i.e. limiting the fields included for each resource)
  • sorting resources
  • paginating primary and related resources
  • filtering resources
  • error statuses and data

The JSON:API site also provides recommendations that go beyond the scope of the base specification:

  • naming members
  • URL design
  • filtering strategies
  • supporting clients lacking PATCH

It's important to note that the base specification as well as the non-normative recommendations complement, and do not contradict, HTTP semantics.

A Thriving Ecosystem

While teams can immediately save time by adopting some of the hard-won conventions embodied by JSON:API, there are much broader and longer lasting benefits that can come from building a fully compliant API.

An ecosystem of JSON:API compliant libraries that span many languages and frameworks is actively being developed. Whether you're building a client or server, you should be able to lean on this ecosystem for assistance. Admittedly, many implementations are still works in progress, in no small part due to changes in JSON:API itself over the past two years. However, now that the spec has stabilized, it's exciting to see implementations come into compliance with 1.0.

The Journey to 1.0

From Draft to Guideline to Specification

JSON:API started its life as a draft with a pretty narrow focus. As it grew in scope, it tended to do so inclusively. Some areas of the spec became so flexible that the matrix of possible options became untenable to fully implement (e.g. URL vs. ID styles, keying primary data by data vs. resource type).

JSON:API gradually became a set of fluid guidelines for developing APIs that was not focused enough to be called a spec.

This "guideline phase" lasted for much of 2014. In retrospect, this period was truly invaluable because it allowed implementers to experiment and discover what worked and what didn't. When Yehuda and I sat down together to rewrite the spec fully in December 2014, we were able to "pave the cowpaths" by choosing the well trodden paths that were working for implementors. We replaced many SHOULDs with MUSTs. The resulting RC2 draft of the spec was much tighter in focus and actually came quite close to being tagged 1.0 in March.

Polishing 1.0

As tempting as it was at the time, it's a good thing that we didn't abruptly release RC2 as JSON:API 1.0. Instead, we decided to give implementations a chance to catch up and test the new spec as a whole. We realized that there were a number of implementations already committed to compliance with the spec and that they needed more time to thoroughly vet its new incarnation.

Two core contributors, Tyler Kellen and myself, have been actively developing compliant libraries. Tyler and his colleagues at Bocoup have been building Endpoints for Node. At Cerebris, Larry and I have been working on a server implementation for Rails, JSONAPI::Resources, as well as a client implementation in JavaScript, Orbit.js. During the final RC3 / RC4 phase, we all pushed to keep these libraries compliant with the spec to validate any changes.

This final phase, perhaps more than any other, was truly a community effort. I'm especially grateful for the contributions of Ethan Resnick, Kalle Tuure, hhware, Ward van Teijlingen, and Christoph Ziegenberg. They all really stepped up in the final months to raise issues and submit pull requests to ensure that JSON:API 1.0 was solid and would be extensible post-1.0. I also really, really appreciate all the time and effort that Tyler invested to help polish the final version of the spec.

I'm so proud of, and grateful to, the JSON:API community for working together so well on difficult problems that have historically been the source of so many arguments. Thanks to you all for making 1.0 happen!

JSON:API 1.0+

I'm looking forward to seeing JSON:API reach its full potential as its ecosystem matures. It shouldn't be long before 1.0 compliant implementations are available for most popular languages and frameworks. I'm also optimistic that compliance testing tools will soon be developed to help validate implementations.

In a nice bit of symmetry, Ember Data is coming full circle to embrace JSON:API like never before. Ember Data's JSON:API adapter and serializer are nearing full compliance. These layers will be very lean since the JSON:API format is also going to be used internally for normalized data. These changes should land with Ember Data 1.0.

With its extensible structure, the spec itself is also poised to evolve in interesting (and non-breaking) ways post-1.0.

For example, I expect that JSON:API will gain further hypermedia capabilities as the concept of links is extended.

Another exciting possibility that we've explored are extensions. Although still experimental, extensions should allow clients and servers to negotiate for the support of features not included in the base spec. One such extension we've explored allows for bulk operations to be performed in a single request.

In short, JSON:API 1.0 is just the beginning. It's a great time to get involved with this project.


If you're interested in learning more about JSON:API, please check out the spec at jsonapi.org.

If you have any questions or suggestions, please file an issue on JSON:API's Github repo.

And if you have any questions for me, please comment below.