Using the Json Api Specification, Part 1
If you have experience with more than one API, you probably have used some APIs that you love and some that you hate. Reasons to love an API include good documentation, detailed responses, and good error messages. A good API is often so well organized that a front end developer looking at one or two endpoints could give a near perfect guess at what the others do, just by their names and HTTP methods.
Problem is, we backend developers like to get creative! With lightweight frameworks like Flask and Sinatra whipping up an endpoint is a cake walk. Couple that with a solid ORM like SQLAlchemy and suddenly, you have an API that gets the job done...so long as the nutty database guy is in direct communication with the client side devs.
Sure, you could write 3 pages of documentation detailing all your custom decisions for every one of the 30 endpoints in your system, many do. Thing is, "good documentation", in front-end speak means, "prewritten code for each endpoint in Ruby, Python, PHP, Node , Java, and Objective-C." I imagine some of you are agreeing and getting very excited about this idea. Sad truth is though, most backend teams don't have the financial or human capital to just give you what you want. Companies like Facebook, Twitter, and Tumblr will, but they aren't the only neat APIs out there, at least they are not the only APIs with information worthy of using.
Because of how delightful and easy these APIs are to use, its easy to get discouraged when building an API. There is a lot to live up to. You can write documentation till you keel over but the chances of the masses reading what you wrote are slim!
The key here, and what those big shots don't seem to understand, is standardization. I can communicate with you here without giving you a "key", because I assume that you'll recognize I'm using the English language protocol. I might add a flourish here and there, but if I stick to what I know you know, we can communicate fast and effectively. An important thing to note here is you can conform to these standards, but you don't have to, I could begin communicating in Yoda speak if I so chose: The computer enforces well known standards for RESTful APIs not. Yes, hmmm.
But I will not be communicating in Yoda speak, and you should not be writing your APIs in your own goofball idea of a way, even if it get's the job done. I have been known to throw small animals softly into the air, gently catch them, and set them down angrily when I notice well respected companies implementing "Yoda speak" APIs. Who is on the naughty list? Well, Twitter only uses POST and GET methods even when a delete is more sensible. Twitter also generally misuses REST, including verbs in resource names. Walmart (used to I happily learned) return a 200 status code even when a request had failed or was malformed. And despite my beef with Twitter, for the most part those guys conform better than anyone. Some APIs are so bizarre it would be impossible to determine the reason for HTTP verbs or status codes at all. The cool thing is though, just as most of us don't speak English perfectly, even a partial implementation of the standard goes a long way. Most APIs do their best to follow these forms, even if they fall short some times.
Before I committed to using JSON API in my latest project I read through a plethora of information. I was worried that since the project utilized neo4j (a graph database) that maybe responses couldn't be as standardized in the same way. I was worried that the responses might include too much or not enough information. I was annoyed that the creative touch of crafting a personal response for each endpoint would be lost. All wrong. I ended up having a blast making my first fully compliant "JSON API" API and I would recommend you try it out too.
Why did I have so much fun? I embraced the standard. As I mentioned, my first project to fully comply with the JSON API spec was an API built around a graphing database. To create my models I used an OGM (object graph mapper -- like an ORM for a graphing database) called NeoModel. NeoModel is relatively new and I emailed the developers before taking it for a spin. After a test run, I was impressed. The way NeoModel works is much like SQLAlchemy: the models all inherit from a shared base class that has a few built in functions. In NeoModel this base class is called StructuredNode in reference to the nodes of the graphing database. A tall can of red bull followed by a 45 minute nap spawned a dream that ended up changing the course of the project forever. I extended the base class creating "SerializableStructuredNode" and added a few methods to the new Base class that created standard JSON responses based on the JSON API spec. After the grueling process of writing this new powerful base class, the rest of that API was done in no time. All that it required was the endpoints themselves -- a significantly easier task than writing cypher (think SQL for neo4j) for 24 endpoints.
Even better? The clients that will use that API don't need documentation. Using the correct HTTP verb, and the correct resource name, they can find any type of node in my database, it's attributes, and it's relationships to other attributes. They can even request that those related resources be individually included in the response because they would rather not send a separate query for them later. If they have any questions I'll send them right to jsonapi.org. It's kick ass.
So you are wondering about my magic class. Yea, it's dope. I haven't yet published it on GitHub or the pip repository because I want to allow a bit more time to work out the kinks, at some point I will though, and I plan to keep you updated on the progress of that here. Secondly, I'd like to write a similar base class for SQLAlchemy. I am getting started on that soon, but have a lot of work and school on my plate at the moment also. Either way, if you are interested in testing, using, or contributing to either of those projects, please let me know. I am very excited about this well thought out and widely applicable standard. Ω
Prev <> Next
(c) 2018 firstname.lastname@example.org