4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-10-01

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

以上です。

参考

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?