There are nearly as many options for API tools and design styles as there are APIs themselves. The modern API industry has a variety of specifications, frameworks, paradigms, architectures, integrations, and extensions that make each API instance unique. Today, we’re going to take a look at three of those options.
In a previous post, we explored the benefits of using JSON:API, a specification for building APIs in JSON. In this piece, we’ll see how the specification compares to some other important design styles and specifications in the API design world, namely REST and GraphQL. We’ll dig into what each of these things are in general terms, consider what makes them unique, and find how they relate to one another.
What is JSON:API?
Simply put JSON:API is “a specification for building APIs in JSON,” originally drafted by Yehuda Katz in May of 2013. Its original goal was to create a communication model based around defined interactions, rather than leaning on per-application “ad-hoc” code. JSON:API sets a standard for communication; it expresses how requests to the server should be formatted, and then what the response to the client should be formatted as. Its goal is to optimize HTTP requests by reducing the number of requests needed as well as reducing the size of the packages themselves.
JSON:API has quite a lot of interesting features. Compound documents allow servers to respond to requests with related resources, which mimics a lot of GraphQL’s functionality without making for an overly complex system. Clients can leverage this to traverse the internal resource layout and grab more complex information.
Clients can also request very specific information by using sparse fieldsets, wherein the client only requests data from a specific resource name and a specific set of desired fields. This makes for much more efficient calls than is otherwise seen in other relational API standards. JSON:API also allows for optionality in features: you can turn anything on or off, with the client being the ultimate source of acceptance or denial.
That, combined with optionality, makes for a powerful limitation of what could otherwise be a bloat-heavy response. Additionally, JSON:API has an effective caching system because everything is using the same JSON:API access scheme when it comes to storing data. In other specifications, data is stored in varying locations, which can make for more complicated and wasteful processing and response.
What is REST?
REST, or Representational State Transfer, is a paradigm and architecture designed by Roy Fielding, the co-author of both the HTTP and URI specifications. REST was designed to provide interoperability between web resources by defining a uniform set of stateless operations. It uses the standard set of GET, HEAD, POST, PUT, PATCH, DELETE, CONNECT, OPTIONS, and TRACE to act upon these resources, which makes its use and response predictable.
Using stateless protocols and standard operations is meant to provide fast performance, reliable interactions (that are known successful before the client makes a request since the request verbiage is standard), and extensibility through standardization. REST is currently the most common method of design for web applications.
REST is built upon the idea of separated resources being acted upon using standard verbiage. Due to this, each request only responds with that which you asked for. This makes for a highly efficient, fast, and powerful approach. Its stateless nature improves nearly everything about the client experience.
REST is by its nature somewhat obfuscated, only giving what is expressly requested. This can add additional security, as its harder to get a sum total view of an entire requested resource when you’re getting limited returned data.
What is GraphQL?
GraphQL is an application query language, It is primarily designed to create a predefined, understandable, and stable format for requests. The official GraphQL website states it most succinctly by saying “describe your data, ask for what you want, get predictable results.”
GraphQL was designed internally by Facebook in 2012 and was publicly released in 2015. It is a reversal of the typical client-server relationship, allowing the client to specifically state the structure of data and the data itself that should be returned from the server. This makes caching more difficult, but grants greater control over the data output, and allows for incredibly complex data relationships to be identified, utilized and extended upon. GraphQL gives information as to related resources, allowing you to traverse from the first returned data to more related data content, forming a graph of related data and meta-relationships.
The main draw behind GraphQL is that the client requests the data and the format that data is then delivered in. This means it provides much more stable, expected data returns, and delivers greater efficiency by only getting that data which is requested, not that which the API server assumes you want.
The provision of related resources also means that you can make more advanced queries and get all of that data in one fell swoop, whereas in other solutions like REST, you’d need to be make hugely complicated multi-endpoint series of calls to get everything you can in a single GraphQL request.
Let’s compare JSON:API to both REST and GraphQL. We should note here that much of what arises here comes from the fact that REST is essentially an architectural paradigm. GraphQL and JSON:API, on the other hand, are both specifications. We’re comparing both here because REST is often used in a plain form, making it a paradigm at its most basic form, and a specification of sorts in its most popular iteration.
Tooling and Community
It should be noted that REST has about as strong a community as a developer could ask for. REST has existed for many, many years at this point. As such, there’s a wealth of tooling, documentation, implementations, integrations, extensions, and more out there that can be leveraged to make your offering that much better. JSON:API and GraphQL are, at least in relation to REST, newer to the scene, and as such, neither boast as broad or deep a community base.
That being said, both GraphQL and JSON:API are compatible with REST, and while the Venn Diagram of offerings that are “REST and also GraphQL” is not 100% (and neither is the case with JSON:API), the tooling and community is still very large.
Schemas, Relationships, and Responses
REST is a set of standard verbiage and thus has an associated “expected” resource schema, but nothing is specifically stated or required. GraphQL functions almost entirely on the concept of schemas, and as such, has developed this aspect of itself to lofty heights. While JSON:API does have basic schemas, they are just that – basic. This can be limiting for APIs that need incredibly complex schema and resource relationships.
This leads to the differences in relationships and responses that are probably the starkest difference between the three. REST can technically provide multiple data objects in a single response, but this is not standardized in any way across the various implementations which would allow this. JSON:API and GraphQL, on the other hand, have very clearly stated response formations and schemas, allowing for adoptees to state multiple data object relationships very clearly. Additionally, REST does not embed any related data by default into responses – both JSON:API and GraphQL do.
With GraphQL and JSON:API, requests are highly efficient. Since all related content is served in one way or another with these two options (and with JSON:API, is referred to as compound documents), you are left with an easy method for transversing from the entry point on the resource to other content. With REST, this requires multiple requests, which bloats a single (albeit complicated) request into a round trip of excessively singular-focus requests. While JSON:API and GraphQL handle this differently, the end result is largely the same, so it bears no further discussion.
Ease of Use
REST is incredibly simple to support. Since REST relies on standard HTTP verbiage and methodologies, almost anything can support REST, requiring little in the way of transformation of the underlying resources. This is largely true with JSON:API as well, which makes it a great contender for moving from standard REST without the excess cost of moving to a more complex specification.
GraphQL, on the other hand, can require specific relational structures and interlocking mechanisms, meaning that, in some cases, your entire API may need to be restructured in terms of resource logic – this can take time, money, and effort that may not justify itself in the end.
GraphQL does not fundamentally lend itself well to caching. GraphQL responses are specifically created for specific queries – as such, certain constants can certainly be cached (like version numbers), but the underlying nature is not exactly supportive of total response caching. Neither REST nor JSON:API suffers from this – caching is built into HTTP, and as such, both technologies natively support it..
One big benefit for both JSON:API and REST is that the level of security is typically higher due to their more limited exposure of resources. GraphQL can expose far too much information with relatively minor misconfigurations, missed needed restrictions, or too liberal response allowances. Fundamentally, GraphQL is about exposing as much related information as possible, and while this can be a benefit, it also makes sizing up the resource network that much easier.
JSON:API is in many ways a much more basic solution than GraphQL, and because of that, it offers a lot of the great functionality of GraphQL-like systems without the heavy complexity that can come with such implementations. This comes with the caveat, of course, that you are ultimately limited by JSON:API in ways that you might not find yourself limited by under GraphQL, which makes adoption of either a tradeoff between functionality and simplicity. Either way, both are leagues more complex than REST in its most basic form (though some would argue that it is almost certain that if you support a GraphQL or JSON:API API, you are also supporting a RESTful API).
JSON:API is a simple, powerful, and efficient specification that does quite a lot despite how uncomplicated it is. This puts it in the middle between GraphQL and basic REST. Whereas GraphQL allows you to do almost anything in terms of call and response, making its complexity somewhat troublesome at times, and whereas REST is simple, powerful, but ultimately limiting in its most basic form, JSON:API operates somewhere in the middle, providing powerful, extensible tools and responses. While never reaching the heights of GraphQL power (and its associated complexities), it nevertheless is a strong contender for that sort of functionality.
This all comes down to what the API specifically needs. REST is still a great paradigm, and as such, it’s not really in danger of dying out any time soon. That being said, more complex functionality is required for many business use cases, and GraphQL can deliver on that in spades.
If you want an efficient system that is more powerful than the limited base form of REST, but less complex than GraphQL while still providing excellent service of related content and a strong caching system, then JSON:API is an excellent choice.
What do you think about JSON:API? Did we miss any major benefits or drawbacks? Let us know in the comments below!