Skip to main content

从 REST 迁移到 GraphQL

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

API 逻辑差异

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

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

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

GraphQL 的重要优势包括:

下面是每种优势的示例。

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

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

curl -v https://api.github.com/orgs/:org/members 

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

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

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

curl -v https://api.github.com/repos/:owner/:repo/pulls 

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

curl -v https://api.github.com/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 https://api.github.com/repos/:owner/:repo/pulls/:number curl -v https://api.github.com/repos/:owner/:repo/pulls/:number/commits curl -v https://api.github.com/repos/:owner/:repo/issues/:number/comments curl -v https://api.github.com/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 } } } } }