GraphQLを調査
現在関わっているプロジェクトにGraphQLを適用して、一般的なAPIの口を用意できないか?という話があがり、GraphQLが適用できそうか調査した。
結論としては、あまり導入するメリットが無さそうだとなったが、メモを残しておく。
GraphQLと対象プロジェクトのデータでのギャップ
既存のプロジェクトのデータをGraphQLのスキーマ定義で表現できるのか?について調べた結果、いろいろとギャップが出た
Genericsに該当するものが無い
型パラメータ部分をinterfaceかunionかで無理やり回避くらいしか無いか?
Mapがうまく取り扱えない
- Key-Valueのペアのリストで表現
type HogeKeyValue { key: HogeType value: HogeValue } type Fuga { name: String hoge: [HogeKeyValue] }
無駄に一段ネストされる
- CustomScalarTypeで回避
- Mapの時点でスカラーとなってしまうため、この先のデータハンドリングができなくなる
Enumがとても単純にしか定義できない
対象プロジェクトでは、インターフェース⇒Enumの実体が複数実装という形でデータを持てるが、これが表現できない
GraphQLではenumはunionで表せない
type定義でラップするなどしないといけない
インターフェースが定義できるが、実際の型にもフィールド定義が必要で手間
interface NamedEntity {
name: String
}
type Person implements NamedEntity {
name: String
age: Int
}
type Company implements NamedEntity {
name: String
employeeCount: Int
}
SELECT * のように全フィールド指定ができない
リクエストで欲しい形そのままで指定が必要
インターフェースを定義できるが、取得時には、実体の型とフィールドを指定しないと駄目
#実体の型ごとに、取得フィールドを指定しないといけない
... on Cylinder {
diameter
height
}
... on Prism {
height
width
depth
}
リクエストする際は、末端のスカラーのフィールドを指定しないと取ってこれない
オブジェクトで止めたりできない
再帰構造をうまくクエリで書けない
再帰構造のスキーマは普通に定義できるが、クエリでfragmentを再帰的に書いたりしてもエラーになる
ただ、クエリをネストして書くことはできる
#こういうのはエラーになる
fragment HogeFields on Hoge {
name
children {
...HogeFields
}
}
# ネストして書くことはできる
query fetchRecursive() {
hoge {
name
children {
name
children {
name
children {
name
}
}
}
}
}
まとめ
フィールドを指定して最低限のレスポンスにできること、スキーマ定義がちゃんとしていれば、自由度高くユースケースにあわせて、データをリクエストできそうなことはメリットで良く述べられているが、MapとリストとGenericsがうまいこと表現しづらいため、既存プロジェクトのデータは取り扱いづらいことがわかった。