Queries

Let's look at what GraphQL queries look like.

The query language of GraphQL is another of its strong points. It allows clients to define both the data to retrieve and the required shape of that data. This means that a GraphQL client can not only be selective about the data to retrieve, but also dictate how the response should be structured!

Compared to REST, this is incredibly powerful and is standardized by the GraphQL specification. With RESTful APIs, since there is no standard, each and every API can implement (or not) features such as include/exclude, pagination, search, and filtering. With GraphQL, there is one well-defined method for many concepts.

A complete learning guide is available on the GraphQL website: https://graphql.org/learn.

For the following examples, we will use the Star Wars GraphQL API, which you can find here: https://github.com/graphql/swapi-graphql. You can try all of the examples through the playground available here: https://graphql.github.io/swapi-graphql.

We'll start with a basic example where a client wants to retrieve the titles of all of the Star Wars movies:

{ 
  allFilms { 
    films { 
      title 
    } 
  } 
} 

In this example, we have used the allFilms query of the Star Wars API and we have asked to retrieve the title property of each item in the films collection.

The GraphQL queries are not JSON, even if they're a bit similar.

Here's an extract of the response that the GraphQL server would return:

{ 
  "data": { 
    "allFilms": { 
      "films": [ 
        { 
          "title": "A New Hope" 
        }, 
        { 
          "title": "The Empire Strikes Back" 
        }, 
        { 
          "title": "Return of the Jedi" 
        }, 
        ... 
      ] 
    } 
  } 
} 

As requested by our GraphQL client, the server has only provided the title property. This feature of GraphQL is incredibly powerful and can greatly improve the network friendliness of your applications.

As you can see, contrary to the queries, the GraphQL responses are using JSON, which means that they can easily be parsed. Not that it is the only possibility, but it is the default one.

Let's look at a second example. This time, our client wants to retrieve the ID, name, and species name of each character in the Star Wars movies:

{ 
  characters: allPeople { 
    people { 
      id 
      name 
      species { 
        name 
      } 
    } 
  } 
} 

The syntax is quite straightforward.

Notice the characters: prefix in front of allPeople. This notation allows us to define an alias. Aliases are useful to further customize the shape of responses.

In return, the server might respond with the following:

{ 
  "data": { 
    "characters": { 
      "people": [ 
        { 
          "id": "cGVvcGxlOjE=", 
          "name": "Luke Skywalker", 
          "species": { 
            "name": "Human" 
          } 
        }, 
        { 
          "id": "cGVvcGxlOjI=", 
          "name": "C-3PO", 
          "species": { 
            "name": "Droid" 
          } 
        }, 
        ... 
      ] 
    } 
  } 
} 

Again, the server has responded with the data that we asked for (no more, no less) and using the shape and structure that we requested.

This is quite simple, isn't it?

One thing to know about GraphQL is that requests are always sent to the same endpoint URL, using either GET or POST. This is in stark contrast with RESTful APIs, where each resource has its own base URL. Some see this as a major weakness of GraphQL and prefer REST's approach with resource-specific URLs.

Some queries allow or require parameters to be passed in.

Here's how our client can retrieve the name and birth year of Luke Skywalker (knowing its identifier):

{ 
  person(id: "cGVvcGxlOjE=") { 
    name 
    birthYear 
  } 
} 

Query parameters are simply passed as key-value pairs.

Here is the corresponding response:

{ 
  "data": { 
    "person": { 
      "name": "Luke Skywalker", 
      "birthYear": "19BBY" 
    } 
  } 
} 

GraphQL can do a whole lot more. For instance, clients can use parameters to request specific/alternative data formats, content translations, and so on. Such transformations can spare client-side applications the hassle of doing it themselves and much more still.