前回はGraphQLを簡単に試してみました。
試してみたコードはチュートリアルに則っているので、非常に簡単でわかりやすいレベルになっています。その中で、もう少し実用的な内容にしてみようと以下の2つを試してみました。
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 } ] } ] }
レスポンスの内容に丁寧にどこかどう間違っているのか書いてあります。