apis, programming

JSON API is a poor standard for RESTful APIs

Recently, I was asked for my opinion on JSON-API as a potential standard for RESTful APIs. While I like the idea of some standardization for RESTful JSON responses, I feel that JSON API woefully misses the mark, and here’s why.

Let’s take the simple example from JSON API’s site

{
  "articles" : [{
      ¨id¨: 1,
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z",
      ¨author¨ : {
          ¨id¨ : 42,
          "name": "John",
          "age": 80,
          "gender": "male"
      }
 }]
}

and let’s take a look at how that could be briefly rewritten as regular JSON to achieve the same functionality


{
  "articles" : [{
      ¨id¨: 1,
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z",
      ¨author¨ : {
          ¨id¨ : 42,
          "name": "John",
          "age": 80,
          "gender": "male"
      }
 }]
}

Now, let’s give a usage example of the JSON API response above, to print all the article titles and author names, which I would imagine is a typical use case for data that looks like this.

for(var data : response.data){
   if(data.type == ¨articles¨){
    print data.attributes.title;
    var author_id = data.relationships.author.data.id;
    var author_type = data.relationships.author.data.type;
  }
}
  for(var inc : response.included){
    if(inc.id == author_id && inc.type == author_type){
      print inc.attributes.name;
    }
 }

compared to the regular JSON, where you can print the variables simply by writing

for(var article : response.articles){
  print article.title;
  print article.author.name;
}

JSON API is the obvious poor choice here. We can see

  • 3x the implementation cost of regular JSON (12 line vs 4 lines)
  • O(n) execution time vs O(1) execution time, with no temporary variables required
  • Increased code complexity, poor readability and higher maintenance cost vs regular JSON

Ultimately, I get the impression that JSON-API’s approach is trying to treat JSON as a message-passing format, but in doing so it misses the biggest advantage of JSON, which is that it’s an Object Notation.

The structures in JSON – numbers, booleans, strings, keys and objects – can be read natively by any modern, object-oriented programming language. A well-designed JSON response can be parsed directly into an object model by the receiving application at low cost, and then used directly by that program’s business logic. This has been well-understood by the creators of JSON-schema and Open APIs (formerly Swagger), which effectively add type-safe behavior to JSON’s constructs which are dynamic-by-default.

Thus, if you want to describe hypermedia in JSON, you should do so in context, the same way we do on the web.
Hyperlinks on the internet are identified by convention – either by being underlined or by text coloring. A similar approach is valid for JSON responses. Hypermedia is already quite identifiable in a JSON response because it’s a string starting with http:// 😉  Machines can find it by the url type in a corresponding Open API specification. The benefit of re-enforcing it with conventions like keywords (such as href, used by the HAL specification) or a prefix (like starting the field-name with an underscore, like _author,) is that it adds clarity for those reading code that handles the response model.

I think this is the type of clarify we should be aiming for designing standard for RESTful JSON APIs.

Advertisements
apis, programming, travel

Innovation starts with good APIs

(Written on September 21st, but only got around to publishing now)

I’ve spent much of the last two weeks, along with several of my colleagues, developing an entry for tHACK SFO 2012. I love these hack competitions – they can sometimes seem like a waste of time but they’re an important driver of solid technical skills, an opportunity to play with some new APIs or tools, and a driver of that overused buzz-word innovation.

The travel industry has an enormous variety of APIs – some are great, but most of which stink, and the APIs made available to us for tHACK really came from all ends of that spectrum. (Well, actually, to be fair, there were no real stinkers!)

One remarkable point that stuck me while coding was how much easier it is to include a great API in an application, than a poor one. We wrote our prototype as a Facebook app – I’d already used Facebook’s API before and I knew it was good, but writing the prototype was a pointed reminder of how much better it is than any in the travel industry. Accessing the features of Facebook within our app was simple, the requests and responses were easy to understand, and the results were fast and reliable.

This made the contrast between many of the competition-offered APIs brutally stark. Many travel industry APIs are intensely frustrating to use – and it was evident during the presentation of the hacks which ones were easy to use, and which ones were  trouble. There were 9 APIs provided, and 18 hacks. Of the 9 APIs provided, only 4 were used by more than one of the hacks. Of the remaining 5, 2 were used by independent competitors, 2 were used only in hacks published by the same company as published the API, and one was not used at all (1).

Here were some of the issues I encountered with those APIs – take it as a list of red flags to be noted when releasing a new API

  • Hard to connect. Soap wrappers are hard to use and rarely necessary these days – if your API is not RESTful, there better be a good reason for that.
  • Login to the API can be a tricky problem, but it should not require a persistent data store on my behalf. In particular, many APIs make a meal of OAuth. I know that OAuth’s a difficult paradigm, but with a bit of thought and understanding, a sensible implementation is possible.
  • If your API model doesn’t send or recieve in either XML or JSON, forget it. Simple tools are available to serialize/deserialize both XML and JSON APIs as constructs in virtually any programming language. Almost every other data transfer mechanism will require serialization by hand, a massive time constraint.
  • Your API should send and receive in the same data format. Sounds obvious, but it’s often ignored. If replies are in JSON, send should also be in JSON
  • Sensible data models with few surprises. A hallmark of an excellent API is rarely having to refer to the documentation. Interface objects should be sensibly named and constrained. Encoded data should use clearly named enumerations, ideally with a full-text translation, not integer codes.
  • Less chit-chat. Saving data, for example, should be a one-call operation – no excuses. For a simple flow, I should be able to send or receive all the data I need in no more than 3 API calls. More calls mean that you’re passing your orchestration and performance problems to me.
  • If a given API call is not fast, it should be ansynchonous. Give me an answer, or give me a token

Providing language SDKs is not enough! Not everyone wants to program in your programming language of choice. In any case, by pushing the hard work to the API means that clients of that API don’t have to implement those features individually, or in a variety of SDKs.

The proof was in the results. With only a couple of exceptions, the quality of the entries in tHACK SFO was unanimously high. (Check out iPlanTrip or Concierge for starters!) However, the judges gave no rewards to the users of difficult APIs, all the winning and highly commended hacks were based on the 5 easy APIs, and all of them used either Geckgo or Vayant, which struck me as being the two APIs that best combined content and ease-of-use. Those who took the time to figure out and use the more complex APIs had less time to produce high quality integrations.

Finally, a shout out to Vayant, the Amadeus Hotel Team and Rezgo whose APIs helped us produce a slick and innovate app – hopefully the people at Amadeus will let us publish tVote for you sooner rather than later.

(1) These figures come from my recollection of the event the following day. If you have official figures to confirm them, that would be nice.