The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Miscellaneous GraphQL Syntax

Many programming and data-access languages have bits and pieces, or odds and sods, of miscellaneous syntax that are important, yet not important enough to warrant their own chapter in a book.

This chapter covers some of that syntax, with respect to GraphQL.

Arguments on Nested Fields

Back in the chapter on variables and arguments, we saw how root fields can take arguments, to make it easier to pass in details that may vary by invocation:

query find($search: String!) {
  findTrip(searchFor: $search) {
    id
    title
    startTime
    priority
    duration
  }
}

Here, the argument is applied to one of the root query fields, findTrip. This feels fairly typical and a bit reminiscent of passing parameter values to Java methods.

However, fields other than root fields might also accept arguments. These can have the same sorts of roles as do arguments on root fields: sort order, pagination, etc. Here are some other scenarios where arguments on nested fields may prove useful.

Scenario: Conversion

Sometimes, the argument might be for simple things like format or unit conversion:

query find($search: String!) {
  findTrip(searchFor: $search) {
    id
    title
    startTime
    priority
    duration(timeUnit: DAYS)
  }
}

Here, a (theoretical) revised version of our server takes a timeUnit argument on duration, from some (theoretical) enum where one of the values is DAYS. This would be akin to using TimeUnit.DAYS in Java date/time conversions.

Typically — though not universally — fields in this scenario will have a default value for the argument. That way, you can either include the argument or skip it, as you see fit. If you skip the argument, some default format or unit will be used (e.g., minutes in the case of duration).

Scenario: Filtering

Sometimes, the argument might be for restricting the data to some subset:

query find($search: String!) {
  findTrip(searchFor: $search) {
    id
    title
    startTime
    priority
    duration(timeUnit: DAYS)
    plans(type: FLIGHT) {
      id
      title
    }
  }
}

Here, another (theoretical) revised version of the server takes a type argument on plans, for some (theoretical) enum where one of the values is FLIGHT. This might be used by the server to only return those plans that are flights, not lodging stays, for clients that only care about the flights.

Once again, often times the argument will have a default value; in the case of filtering, the typical default meaning is “give me everything”.

Developing Clients Using Arguments on Nested Fields

In general, though, the fact that these arguments are nested does not really impact your development of a GraphQL client. Either the arguments are being set from variables, or they are not. Variables are still all declared on the operation itself. So, you might have more variables than before, but the fact that one or more of those variables happen to be used in nested fields’ arguments does not impact how you provide the variables’ values:

Directives

In Java, we have annotations. These are denoted by an @ prefix in front of some symbol, such as @Override or @TargetApi or @Subscribe. This is an extension point for the Java language itself, in effect. Not only can Java provide annotations (e.g., @Override), and not only can Android add more annotations (e.g., @TargetApi), but third-party libraries can define annotations (e.g., @Subscribe from greenrobot’s EventBus). The Java programming language itself provides hooks for libraries to declare available annotations and find out what annotations a developer used (via an annotation processor). However, Java itself does not define what most of the annotations actually are.

In GraphQL, directives fill a similar role. As it turns out, the syntax is also a bit reminiscent of Java annotations, with @ as a prefix before some symbol.

@include and @skip

Two directives are defined at present in the GraphQL specification: @include and @skip. These are opposites:

For example, you might want to use the same GraphQL document for requesting either just the basic trip data or all of its nested plans as well. The server could offer that via dedicated server-side logic:

query all($getPlans: Boolean!) {
  allTrips {
    id
    title
    startTime
    priority
    duration
    plans(sockItToMe: $getPlans) {
      id
      title
    }
  }
}

Here, the (theoretical) sockItToMe argument would be used by the server to determine whether to return the plans or return something else (null or an empty list).

However, GraphQL supports this without custom server logic:

query all($getPlans: Boolean!) {
  allTrips {
    id
    title
    startTime
    priority
    duration
    plans @include(if: $getPlans) {
      id
      title
    }
  }
}

If you execute this in GraphiQL against the public demo GraphQL server, and you set the getPlans variable to true, you get the nested plans. However, if you set the getPlans variable to false, the plans field is ignored and is not returned.

@skip just inverts the role of the boolean variable:

query all($noPlans: Boolean!) {
  allTrips {
    id
    title
    startTime
    priority
    duration
    plans @skip(if: $noPlans) {
      id
      title
    }
  }
}

Here, if noPlans is true, we skip plans; if noPlans is false, we include the plans.

From the standpoint of your GraphQL client, other than having additional variables for the if argument on the @include or @skip directives, there is no effect on your code. These variables are indistinguishable from any other variables that you might be using.

Custom Directives

In theory, you may have access to more directives than this:

Server implementations may also add experimental features by defining completely new directives.

(from the GraphQL documentation).

GraphQL itself may gain more directives in the future as well:

As future versions of GraphQL adopt new configurable execution capabilities, they may be exposed via directives.

(from the GraphQL specification)

The introspection API will supply details of the available directives, and so they should be available in tools like GraphiQL.

Deprecations

The preview of this section is sleeping in.