GraphQLを試す!(enumとPOJO)

前回はGraphQLを簡単に試してみました。

試してみたコードはチュートリアルに則っているので、非常に簡単でわかりやすいレベルになっています。その中で、もう少し実用的な内容にしてみようと以下の2つを試してみました。

  • Schemaにてenumを使用する
  • MapではなくPOJOをレスポンスに指定する

queryの引数にenumを使用する

GraphQLのSchema定義をざっと読んでみたのですが、色々とできることがあるみたいです。その中で、とりあえずenumを使ってみようと思います。enumを使うことのメリットは値の種類を制限することができる点です。種類に該当しない値がやりとりされると、GraphQL側で自動的にエラーとして認識してくれます。

というわけで、以下のSchema定義を記述してみました。

type Query {
    hero(episode: Episode): Character
}

type Character {
    name: String!
    appearsIn: [Episode!]!
}

enum Episode {
    NEW_HOPE
    EMPIRE
    JEDI
}

enumの定義は enum にて行います。あとはその種類を列挙するだけです。

実際にリクエストを送る場合はこのようなリクエストになります。

{
  hero(episode: JEDI) {
    name
    appearsIn
  }
}

MapではなくPOJOをレスポンスに指定する

前回はレスポンスをMapを使って処理していました。しかし、普通だったらPOJOを使いたいですよね。というわけで、上記のSchema定義の Character を以下のように書いてみました。

    data class Character(val name: String, val appearsIn: List<String>)

    fun getHeroDataFetcher(): DataFetcher<Character> {
        return DataFetcher { dataFetchingEnvironment ->
            logger.info("argument is {}", dataFetchingEnvironment.getArgument("episode") as String)
            Character("Anakin Skywalker", listOf("NEW_HOPE", "EMPIRE", "JEDI"))
        }
    }

指定された引数は処理に使っていないのですが、実際になんの値が来たのかを知るためにログ出力しています。ここでスター・ウォーズの例を使っているのは私が好きだからではなく、公式のドキュメントがスター・ウォーズを題材にしているからです。

POJOをレスポンスに使う場合の詳細についてはドキュメントに記載があります。POJOはデフォルトの PropertyDataFetcher がよしなに処理してくれるみたいですね。

動かしてみた

実際に動かしてみました。リクエストとレスポンスはこんな感じになりました。

リクエス

{
  hero(episode: JEDI) {
    name
    appearsIn
  }
}

レスポンス

{
  "data": {
    "hero": {
      "name": "Anakin Skywalker",
      "appearsIn": [
        "NEW_HOPE",
        "EMPIRE",
        "JEDI"
      ]
    }
  }
}

きちんとPOJOクラスが処理されているのがわかりますね。

ここでenumの種類以外の値をリクエストに含めると以下のようにエラーになりました。

リクエス

{
  hero(episode: XXX) {
    name
    appearsIn
  }
}

レスポンス

{
  "errors": [
    {
      "message": "Validation error of type WrongType: argument 'episode' with value 'EnumValue{name='XXX'}' is not a valid 'Episode' @ 'hero'",
      "locations": [
        {
          "line": 2,
          "column": 8
        }
      ]
    }
  ]
}

レスポンスの内容に丁寧にどこかどう間違っているのか書いてあります。