Skip to main content
We publish frequent updates to our documentation, and translation of this page may still be in progress. For the most current information, please visit the English documentation.

从 REST 迁移到 GraphQL

了解从 GitHub 的 REST API 迁移到 GitHub 的 GraphQL API 的最佳实践和注意事项。

API 逻辑差异

GitHub 提供两个 API:REST API 和 GraphQL API。 若要详细了解 GitHub 的 API,请参阅“关于 GitHub 的 API 的信息”。

从 REST 迁移到 GraphQL 代表了 API 逻辑的一次重大转变。 作为样式的 REST 与作为规范的 GraphQL 之间的差异使得很难—且通常不可取—以一对一方式将 REST API 调用替换为 GraphQL API 查询。 我们在下面提供了具体的迁移示例。

将代码从 REST API 迁移到 GraphQL API:

GraphQL 的重要优势包括:

下面是每种优势的示例。

示例:仅获取您所需的数据

单个 REST API 可检索组织成员列表:

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

如果您的目标是仅检索成员名称和头像链接,REST 有效负载中将包含多余数据。 但是,GraphQL 查询仅返回您指定的数据:

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

考虑另一个示例:检索拉取请求列表并检查每个请求是否可合并。 对 REST API 的调用可检索拉取请求列表及其摘要陈述

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

确定拉取请求是否可合并需要分别检索每个拉取请求,查看其详细陈述(大型有效负载),并检查它的 mergeable 属性是真还是假:

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

使用 GraphQL,可以仅检索每个拉取请求的 numbermergeable 特性:

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

示例:嵌套

通过嵌套字段查询,可将多个 REST 调用替换为更少的 GraphQL 查询。 例如,利用 REST AP 检索拉取请求及其提交、非评审注释和评审需要四个单独的调用:

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,可以利用嵌套字段通过单个查询检索数据:

{
  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
          }
        }
      }
    }
  }
}

也可以通过用变量替换拉取请求编号来扩大此查询的能力。

示例:强类型化

GraphQL 架构属于强类型化架构,可使数据处理更加安全。

考虑一个利用 GraphQL 突变向问题或拉取请求添加注释,并错误地将 clientMutationId 值指定为整数而非字符串的示例:

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

执行此查询将返回错误,并指定此操作的预期类型:

{
  "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 可将此值从整数转换为字符串,预期类型为:

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