Why you don’t need a framework to access GraphQL endpoints (Scala edition)

What is GraphQL?

The essence of a GraphQL request is super-simple. You send a post request with a query in the body and the GraphQL server responds with the the results of your query as JSON. There are a few things that can trip you up, but once you are aware of them, you can easily make GraphQL calls without using any special frameworks.

Example GraphQL Request/Response

Anatomy of a GraphQL Request

query {
tracks(
where:{
videoReferenceUuid:{
equals:"e689d163-3753-4892-9955-a30f99f19684"
}
}
) {
id
maxSurpriseId
videoReferenceUuid
varsConcept
predictedVarsConcept
events {
id
uuid
x
y
width
height
time
}
}
}

Before you send that in your the body of an HTTP POST request, it needs to be converted to JSON. The steps to do that are:
1. Strip out all the line feeds from your GraphQL query.
2. Escape the double quotes so that "becomes \".
3. Build JSON like {"query": "<insert your graphql here>"}

So for example the above query would be come:

{"query": "query {  tracks(    where:{      videoReferenceUuid:{        equals:\"e689d163-3753-4892-9955-a30f99f19684\"      }    }  ) {    id    maxSurpriseId    videoReferenceUuid    varsConcept    predictedVarsConcept    events {      id      uuid      x      y      width      height      time    }  }}      "}

Parsing a GraphQL Response

{
"data": {
"tracks": [
{
"id": 26,
"maxSurpriseId": 1386,
"videoReferenceUuid": "21d00e55-...",
"varsConcept": "Unknown",
"predictedVarsConcept": "Chionoecetes tanneri",
"events": [ ... ]
}
]
}
}

When parsing the response, be sure to walk the JSON tree down through data > <my_object_name> .

Example in Scala

The first class is GraphQL.scala. It hides the boiler plate details of formatting the GraphQL query as JSON, sending the POST request (using OkHttp), and converting the responses JSON to Scala case class (using Circe). As a user the only method I care about in it is queryToFuture

The second class, TrackService.scala, shows an example using GraphQL.scala. I’ve omitted the case classes and circe codecs from brevity. Note at line 43, that I’ve passed List("data", "tracks") as a parameter. As mentioned in the “Parsing a GraphQL Response” section above, this is the JSON path to walk to get to the actual data I care about in the response.

Polyglot coder. Deep-sea Researcher. Zazen aficionado. I think squids are pretty cool.