# RESTからGraphQLへの移行

GitHubの REST API からGitHubの GraphQL API に移行するためのベスト プラクティスと考慮事項について説明します。

## APIのロジックに関する差異

GitHub には、REST API と GraphQL API の 2 つの API が用意されています。
GitHubの API の詳細については、「[GitHubの REST API と GraphQL API の比較](/ja/enterprise-server@3.22/rest/about-the-rest-api/comparing-githubs-rest-api-and-graphql-api)」を参照してください。

RESTからGraphQLへの移行は、APIロジックの大きな変化を示します。 スタイルとしての REST と仕様としての GraphQL との違いのために、REST API の呼び出しを GraphQL API のクエリに 1 対 1 で置き換えることは難しく、—しばしば望まない—結果になります。 移行の具体的な例を以下に示しました。

コードを [REST API](/ja/enterprise-server@3.22/rest) から GraphQL API に移行するには、以下を行います。

* [GraphQL 仕様](https://spec.graphql.org/June2018/)を確認する
* GitHubの <c0>GraphQL スキーマ\</c0 を確認します>
* 現在、GitHub REST API とやり取りしている既存のコードを検討する
* [Global ノード ID](/ja/enterprise-server@3.22/graphql/guides/using-global-node-ids) を使用して API バージョン間でオブジェクトを参照する

GraphQLによる重要な利点には以下があります。

* [必要とするデータだけを取得できる](#example-getting-the-data-you-need-and-nothing-more)
* [入れ子になったフィールド](#example-nesting)
* [強い型付け](#example-strong-typing)

以下にそれぞれの例を示します。

## 例：必要なデータだけを取得

1つのREST API呼び出しで、Organizationのメンバーのリストを取得します。

```shell
curl -v http(s)://HOSTNAME/api/v3/orgs/:org/members
```

目的がメンバー名とアバターへのリンクの取得だけなのであれば、このRESTのペイロードには過剰なデータが含まれています。 しかし、GraphQLのクエリでは指定した内容だけが返されます。

```graphql
query {
    organization(login:"github") {
    membersWithRole(first: 100) {
      edges {
        node {
          name
          avatarUrl
        }
      }
    }
  }
}
```

別の例を考えてみましょう。プルリクエストのリストを取得して、それぞれがマージ可能かをチェックします。 REST API を呼び出すと、pull request とその [概要表現](/ja/enterprise-server@3.22/rest#summary-representations)の一覧が取得されます。

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls
```

pull request がマージ可能かを判断するには、個別にそれぞれの pull request の[詳細な表現](/ja/enterprise-server@3.22/rest#detailed-representations) (大きなペイロード) を取得し、その `mergeable` 属性が true か false かをチェックする必要があります。

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
```

GraphQL では、各 pull request の `number` 属性と `mergeable` 属性のみを取得できます。

```graphql
query {
    repository(owner:"octocat", name:"Hello-World") {
    pullRequests(last: 10) {
      edges {
        node {
          number
          mergeable
        }
      }
    }
  }
}
```

## 例：入れ子

入れ子になったフィールドにクエリを行うことで、複数のRESTの呼び出しを少数のGraphQLクエリに置き換えられます。 たとえば、**REST API** を使って、コミット、非レビュー コメント、レビューと一緒に pull request を取得するには、4 つの別々の呼び出しが必要になります。

```shell
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/commits
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/issues/:number/comments
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/reviews
```

**GraphQL API** を使えば、入れ子のフィールドを利用して単一のクエリでこのデータを取得できます。

```graphql
{
  repository(owner: "octocat", name: "Hello-World") {
    pullRequest(number: 1) {
      commits(first: 10) {
        edges {
          node {
            commit {
              oid
              message
            }
          }
        }
      }
      comments(first: 10) {
        edges {
          node {
            body
            author {
              login
            }
          }
        }
      }
      reviews(first: 10) {
        edges {
          node {
            state
          }
        }
      }
    }
  }
}
```

また、pull request 番号の[変数を置き換える](/ja/enterprise-server@3.22/graphql/guides/forming-calls-with-graphql#working-with-variables)ことで、このクエリの機能を拡張することもできます。

## 例：強力な型付け

GraphQLスキーマは強く型付けされており、データの扱いが安全になっています。

GraphQL [ミューテーション](/ja/enterprise-server@3.22/graphql/reference)を使用して問題または pull request にコメントを追加し、[`clientMutationId`](/ja/enterprise-server@3.22/graphql/reference/issues#mutation-addcomment) の値に文字列ではなく整数を誤って指定する例を考えてみましょう。

```graphql
mutation {
  addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}
```

このクエリを実行すると、この操作に期待される型を指定したエラーが返されます。

```json
{
  "data": null,
  "errors": [
    {
      "message": "Argument 'input' on Field 'addComment' has an invalid value. Expected type 'AddCommentInput!'.",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ]
    },
    {
      "message": "Argument 'clientMutationId' on InputObject 'AddCommentInput' has an invalid value. Expected type 'String'.",
      "locations": [
        {
          "line": 3,
          "column": 20
        }
      ]
    }
  ]
}
```

クオートで `1234` をラップすると、この値を整数値から期待されている型である文字列に変換できます。

```graphql
mutation {
  addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}
```