Selecting a Data Type for a RESTful API

Selecting a JSON Media Type

 

Our Engineering group is rounding out a new RESTful API that you can use to build your own apps and incorporate Phone.com functionality into your business systems.

 

We never questioned whether or not we’d use REST—it’s pretty much a given that REST is the best way to build an API. And it’s almost as unanimous that a RESTful API should be JSON based. But since REST is a set of architectural guidelines, rather than a protocol or specification, we had to decide at the outset which media type we would use for output. That is, what kind of JSON structure would we use to convey our data.

 

There is no widely agreed upon way of doing RESTful data structures, which led us to a lengthy analysis of no less than six different proposed standards! We’d like to share a little about our research and the decision we made.

What We Were Looking For

Our initial goals were pretty simple:

  1. Avoid developing our own format from scratch. The world does not need another JSON REST media type!
  2. Select a type that’s simple and easy for developers to understand, while covering our needs and use cases.

 

We found a bewildering variety of choices: HAL, JSON-LD, Siren, JSON API, Collection+JSON and Mason all caught our attention, and while I don’t have time to give detailed structure comparisons, I do want to review each one and offer our commentary.

HAL (Hypertext Application Language)

The granddaddy of all JSON REST formats, HAL was first proposed in 2011. It’s a lightweight specification that focuses mainly on linking between API resources.

 

We like HAL for its simplicity. Unfortunately, it’s too simple for our purposes. HAL doesn’t support forms—only links—and it has no support for advanced topics like error handling. We did, however, like how it provides for embedded resources and multiple links with the same relationship.

JSON-LD (JSON for Linked Data)

This is another early, lightweight format. JSON-LD is mainly intended for backporting link structures onto existing JSON APIs. At its core, it doesn’t support advanced requirements either, although there is an extension of sorts called Hydra, which attempts to address this weakness.

Since our API is totally new, we have no need for JSON-LD’s primary use case, which is retrofitting existing JSON APIs. So we kept looking.

Siren

A newer JSON media type is Siren. While we appreciated its handling of forms, Siren has no error handling and insufficient support for complex POST or PUT requests. Also, we found its concept of defining media subtypes in a class property to be awkward and underdeveloped, and we did not like its stricter data structure, which requires data to be encapsulated in a properties object.

JSON API

Farthest along the trend toward strict specifications is JSON API. It has the longest and most detailed spec of all the media types we considered. It even goes as far as defining which HTTP status codes must be returned, and how input parameters must be processed. For those who are willing to cede nearly every interface design decision to a specification, it doesn’t get any better than this.

 

However, the Phone.com API’s needs are complicated in several areas and we were not convinced that JSON API could handle 100 percent of it without having to defy the spec—and an implementation with significant deviations from the spec is little better than having no spec at all.

 

Also, we believe the way JSON API consolidates objects into its included array might be good for clients that want to rely heavily on caching the data, but it really complicates the data structure and makes it difficult to see what’s there. While this is no problem once the client application is complete, an API’s usability is most relevant during the process of writing the client, not afterwards. Developers must be able to quickly and easily understand what’s there in order to write the client in the first place.

Collection+JSON

We found that Collection+JSON (now incorporated into a variant called Collection.Dot+JSON) is great for APIs that use lists heavily, which certainly applies to the Phone.com API. We also appreciated that it would handle some of our advanced use cases beyond just linking. However, Collection+JSON imposes a rigid data structure that requires everything to be structured as a list, even API endpoints that represent a single object.

Mason

Last but by no means least, we explored Mason—specifically, Draft 2. While relatively unknown in the JSON REST API community, we found it to be a very robust option, with the flexibility to handle our various use cases. Mason has specifications for error handling and sophisticated form support. It also includes specs for multipart/form-data requests, which is rare for a JSON media type.

 

With forms, Mason includes explicit support for JSON-Schema in addition to templated URLs, making it extremely flexible. It’s also more developer friendly by allowing for human-readable titles and descriptions, which can be turned off in production through a special request header.

 

Draft 2 also incorporates an innovative idea with links and forms. Almost every other media type splits forms and links into separate lists, but Mason combines them into a single @controls property. This leads to simpler data structures and a more natural grouping of all the different options an API client might be offered for a given resource.

 

Overall, we found a lot to like with Mason! The only real shortcoming we found was a lack of awareness among developers. It’s only been around for a couple years.

Deciding on a JSON Type

After our first review of each media type, we came to appreciate those that pay attention to advanced use cases, such as error handling and forms. We initially gravitated toward Collection+JSON, but our concerns about data-structure rigidity and awkward handling of non-list data led us to look elsewhere. We ultimately fell in love with Mason Draft 2. We feel it strikes the best balance between robustness and developer friendliness.

Post Implementation

Three months have passed since making our decision to use the Mason data type. During this time, we’ve written not one but three different Mason APIs, and we couldn’t be happier!

 

For your reference, we’ve open-sourced two PHP libraries to help with this kind of task. Feel free to check them out!

 

We’d love to hear your thoughts on selecting a JSON data type for your API project. What led you to select one of the types above, or yet another data type I haven’t mentioned?