API 逻辑差异
从 REST 迁移到 GraphQL 代表了 API 逻辑的一次重大转变。 作为� �式的 REST 与作为规范的 GraphQL 之间的差异使得很难—且通常不可取—以一对一方式将 REST API 调用替换为 GraphQL API 查询。 我们在下面提供了具体的迁移示例。
要将代� �从 REST API 迁移到 GraphQL API:
- 查看 GraphQL 规范
- 查看 GitHub 的 GraphQL 架构
- 考虑您当前的现有代� �如何与 GitHub REST API 交互
- 使用全局节点 ID 引用 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,可以仅检索每个拉取请求的 number
和 mergeable
属性:
query {
repository(owner:"octocat", name:"Hello-World") {
pullRequests(last: 10) {
edges {
node {
number
mergeable
}
}
}
}
}
示例:嵌套
通过嵌套字段查询,可将多个 REST 调用替换为更少的 GraphQL 查询。 例如,利用 REST API 检索拉取请求及其提交、非评论注释和评论需要四个单独的调用:
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!"}) 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
}
}
}
}
} mutation {
addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
clientMutationId
commentEdge {
node {
body
repository {
id
name
nameWithOwner
}
issue {
number
}
}
}
}
}