Understanding the Rise of GraphQL: GraphQL vs. a JSON DSL
Let's look at GraphQL and why it is a better choice than a JSON DSL. Do you agree? Let us know in the comments.
Join the DZone community and get the full member experience.
Join For Free
It turns out that GraphQL is pretty awesome. I didn’t always see it that way. The first few times I ran across GraphQL, I was pretty skeptical of its touted benefits because the cost of putting together a GraphQL system seemed too high. It also seemed to me that all the benefits of GraphQL could still be achieved by just creating a custom JSON DSL (query language using JSON).
For example, a “read” query might look like this in GraphQL:
But if we were to use a custom JSON query language, we might have come up with this ourselves:
As you can see, the JSON DSL is “uglier” but it’s a lot more flexible, no additional tooling, and you can create your own “query language.”
Benefits of a JSON DSL:
- No change in tooling on the client
- JSON objects can be easily manipulated, especially in a language like Javascript where JSON can easily be parsed into a Javascript object.
- No change in tooling on the server
Directives and fragments in GraphQL would not even be required in JSON because you can just manipulate a POJO (plain old javascript object) exactly the way you need to.
The Problems With a JSON DSL
However, the JSON DSL approach has a few problems that start emerging when you deploy it over a long-running software project or a large team.
Problems on the Client-Side:
Where is the “grammar” of your JSON DSL? REST-ish endpoints propose a simple, if slightly ad-hoc, grammar with HTTP verbs and simple JSON being chucked back and forth. But in a custom JSON DSL what if the “query language” changes on the server side? How you do create a specification for the client to create queries in JSON that are valid?
With a REST-ish design, there’s no query language. The JSON that is sent back and forth adheres to a “shape” or a skeleton but not really a dynamic query language. For example, you “POST” an “object.” This allows the creation of things like a “swagger” spec. For example, a “swagger” specification of your API would look like this:
However, what is the “swagger” equivalent for a single HTTP endpoint that takes our JSON query? A query language follows a “grammar” and not really a “shape”.
On the Server-Side:
Serving a JSON DSL based API requires that you:
- Need to parse the incoming JSON query and
- Analyse the parsed query to perform type-checks
- Convert it to an internal form that you can break down and process (“resolving”)
This is suddenly turning from a fun
“oh-hey-i’ll-just-use-some-clever-if-else-statements-to-validate-the-JSON” into
“why-is-this-a-1000-line-conditional-block” or even worse
“who-will-ever-maintain-this-random-new-language-that-exists-only-in-the-mind-of-the-first-employee” situation.
Then, once you start off writing it in a naive way, you’ll soon realise that it’s easier to write a mini-compiler into your API server as a query parser + “resolver” that can actually understand the JSON DSL and process it in phases as opposed to dealing with the JSON DSL in an ad-hoc way.
Welcome to GraphQL
Once you go through the effort above, you’ll realize that you’ve invented a GraphQL. But it’s “uglier” (because there seems to be some key-value cruft), and there’s no standard spec.
GraphQL approaches the problem of being able to make queries against a server by enforcing a few key ideas.
Idea #1: A Standard “Grammar” for Querying
GraphQL defines a standard grammar for a query language to read/write data. It kind of looks like a neater JSON with just the keys and allows you to pass arbitrary parameters in the query.
Idea #2: Force the Server to Publish a Schema
The GraphQL spec mandates that a GraphQL server should publish a schema describing the types of the data and the “parameters” (arguments per GraphQL).
Image taken from graphql.org
When the server publishes a schema, suddenly a whole host of tools and plugins become possible which can start solving the problems that were fundamental to using APIs. In fact, this suddenly makes a GraphQL server + client system better even if you didn’t have to make “queries” and could have just gotten away with simple REST.
The API specification is a part of writing the source code!
Awesome Problem Solved #1: API Validation at Build Time
Whether you’re making “queries” or simple REST calls this idea of having a schema now allows you (or even better, the community ;)) to write tooling that can validate your API calls.
In fact, you can even add IDE tooling to do that validation as you write code!
ESLint configured with Atom to validate GraphQL queries
For typed language clients like Java (Android) or Swift (iOS), you can even generate the SDK code directly and nuke a large amount of boilerplate.
Awesome Problem Solved #2: Reduction in Async Client Code Boilerplate
Async API calls from the client can now be specified as declarative queries and the boilerplate that fetches the data and renders the UI can be neatly abstracted away. This allows you to write much cleaner UI code!
Check out a list of awesome react clients here.
Important note: GraphQL doesn’t itself solve these problems. It’s design choices allow the community to solve these problems.
GraphQL is Awesome
Yes, but even more so, the GraphQL community is awesome! Client-side tooling would have been a nightmare for a whole new query language, but amazing client-side tools are paving the way. Apollo’s react/react-native GraphQL client library even reduces the boilerplate required to use the results of the GraphQL query in your react component!
GraphQL servers are still a bit of a pain to write compared to writing simple REST-ish servers. A backend developer can’t think with URL paths and good old JSON and instead needs to deal with an abstract syntax tree and “resolvers” up front. Add authentication to the mix and the resolution logic becomes a little more complicated. Performance also gets harder to reason about because of the recursive nature of processing a GraphQL query. exAspArk talks about the (n+1) problem and approaches to solving it here.
But these really are teething problems in the ecosystem and the tide is turning with tools that offer ready-to-use GraphQL APIs like the Hasura GraphQL Engine, Postgraphile, etc. Better and better tooling and more discussions around different patterns will start emerging and making life easier for the backend developer!
Summary
GraphQL is an amazing leap forward for consuming APIs! GraphQL is a million times better than writing your own query language in JSON especially if you care about your colleagues and the longevity of your project. In fact, consuming GraphQL is far better than consuming REST because of the type-safety tooling that’s built into the GraphQL server and the client-side tooling. GraphQL servers are still a little hard to write, but it’s getting better day-by-day thanks to the tireless work of folks in the community!
Opinions expressed by DZone contributors are their own.
Comments