Edited at

Github GraphQLのクエリーに対応する構造体を作るだけでレスポンスのJSONとマッピングしてくれるGoのライブラリ「githubql」

More than 1 year has passed since last update.

GoでGithub APIのGraphQLのクライアント githubql を使ってみました。


githubqlの使い方

基本的にはGraphQLのqueryやmutationに合わせたGoの構造体を定義するだけです。

まずgithubqlのページに載っているサンプルを見てみましょう。

以下のようなシンプルなqueryの場合、

query {

viewer {
login
createdAt
}
}

このように構造体を定義し、

var query struct {

Viewer struct {
Login githubql.String
CreatedAt githubql.DateTime
}
}

client.Queryを実行すると戻り値にGithubのGraphQL APIの結果が入っています。

err := client.Query(context.Background(), &query, nil)

if err != nil {
// Handle error.
}
fmt.Println(" Login:", query.Viewer.Login)
fmt.Println("CreatedAt:", query.Viewer.CreatedAt)


今回試すクエリー(GraphQL Explorerの場合)

GithubのGraphQL APIはこちらで簡単に実行結果を確認することができます。

https://developer.github.com/v4/explorer/

今回はGithubにあるGraphQL関連のRepositoryとその言語を5件抽出するクエリーを書きました。

query {

search(query: "GraphQL", first: 5, type: REPOSITORY) {
edges {
node {
... on Repository {
nameWithOwner,
url,
languages(first:5) {
edges {
node {
... on Language {
name,
color
}
}
}
}
}
}
}
}
}


結果

{

"data": {
"search": {
"edges": [
{
"node": {
"nameWithOwner": "facebook/graphql",
"url": "https://github.com/facebook/graphql",
"languages": {
"edges": [
{
"node": {
"name": "Shell",
"color": "#89e051"
}
}
]
}
}
},
{
"node": {
"nameWithOwner": "graphql-go/graphql",
"url": "https://github.com/graphql-go/graphql",
"languages": {
"edges": [
{
"node": {
"name": "Go",
"color": "#375eab"
}
}
]
}
}
},

・・・以下省略


githubqlで書く場合

上記のクエリーをgithubqlを使ってGoで書くと以下のようになります。

Githubのトークンを使ってclientを初期化します。

src := oauth2.StaticTokenSource(

&oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)

client := githubql.NewClient(httpClient)

続いてRepositoryとLanguageの構造体を定義します。

type Language struct {

Name githubql.String
Color githubql.String
}

type Repository struct {
NameWithOwner githubql.String
Url githubql.String
Languages struct {
Nodes []struct {
Language `graphql:"... on Language"`
}
} `graphql:"languages(first: 5)"`
}

GraphQLの引数を指定したいときは構造体にgraphql:"... on Language"のようにタグをつけます。

Searchも構造体で定義します。最初はここが分からなくて少しハマりました。先程のRepositoryの定義もSearchの中に入れ子で書けますが、今回は分けて書いてます。

var query struct {

Search struct {
Nodes []struct {
Repository `graphql:"... on Repository"`
}
} `graphql:"search(first: 5, query: $q, type: $searchType)"`
}

Searchに渡すクエリパラメータを利用する時は、mapを作って渡します。

variables := map[string]interface{}{

"q": githubql.String("GraphQL"),
"searchType": githubql.SearchTypeRepository,
}

err := client.Query(context.Background(), &query, variables)

以下が全体のソースです。


graphql-client.go

package main

import (
"golang.org/x/oauth2"
"os"
"fmt"
"context"
"github.com/shurcooL/githubql"
)

func main() {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)

client := githubql.NewClient(httpClient)

type Language struct {
Name githubql.String
Color githubql.String
}

type Repository struct {
NameWithOwner githubql.String
Url githubql.String
Languages struct {
Nodes []struct {
Language `graphql:"... on Language"`
}
} `graphql:"languages(first: 5)"`
}

var query struct {
Search struct {
Nodes []struct {
Repository `graphql:"... on Repository"`
}
} `graphql:"search(first: 5, query: $q, type: $searchType)"`
}

variables := map[string]interface{}{
"q": githubql.String("GraphQL"),
"searchType": githubql.SearchTypeRepository,
}

err := client.Query(context.Background(), &query, variables)
if err != nil {
fmt.Println(err)
}

for _, repo := range query.Search.Nodes {
fmt.Println("---------")
fmt.Println(repo.NameWithOwner)
fmt.Println(repo.Url)
for _, lang := range repo.Languages.Nodes {
fmt.Println(lang.Name)
fmt.Println(lang.Color)
}
}
}



実行結果

クエリーで定義した構造体に、GraphQL APIからのレスポンスのJSONがマッピングされています。

---------

facebook/graphql
https://github.com/facebook/graphql
Shell
#89e051
---------
graphql-go/graphql
https://github.com/graphql-go/graphql
Go
#375eab
---------
Youshido/GraphQL
https://github.com/Youshido/GraphQL
PHP
#4F5D95
---------
graphql-elixir/graphql
https://github.com/graphql-elixir/graphql
Elixir
#6e4a7e
Erlang
#B83998
---------
GraphQLSwift/GraphQL
https://github.com/GraphQLSwift/GraphQL
Swift
#ffac45

以上です。


参考