通过 sgcOpenAPI 获得 GitHub REST API Delphi 客户端

GitHub 维护着公开发布的最大 OpenAPI 描述之一,并以 MIT 许可证发布。sgcOpenAPI 提供的不是手写的 GitHub 组件,而是一个生成器。对 api.github.com.json 执行一条命令行,就会产出一个 Pascal 单元,包含 1,225 个方法、每个方法一个类型化的响应类,以及一个 GetOpenAPIClient 函数,直接交给您一个可用的客户端。

GitHub + sgcOpenAPI

下面的数字来自对当前描述运行生成器并编译其结果的实测,不是估算。

源规范

github/rest-api-description 中的 descriptions/api.github.com/api.github.com.json,声明为 OpenAPI 3.0.3,无需任何转换步骤。

生成结果

813 条路径变成 1,225 个方法和 1,134 个响应类,另有 3,250 个模型类,全部位于一个约 274,000 行的单元中。

身份验证

使用 -a 2 生成,并在运行时设置 Authentication.Token.BearerToken。个人访问令牌和安装令牌都适用。

可以编译

生成的单元在 RAD Studio 12 的 Win32 平台上干净编译通过,库路径上除了 sgcOpenAPI 的 Source 文件夹之外无需任何内容。

运行生成器

GitHub 为同一份描述发布了多个版本。api.github.com.json 描述托管服务,ghes-3.x.json 描述 GitHub Enterprise Server。针对哪一个,就用哪一个生成。

> sgcOpenAPI.exe -i "api.github.com.json" -o "github.pas" -a 2

File successfully created github.pas

-i 接受本地文件或 URL,JSON 和 YAML 都可以。-o 是要写出的 Pascal 单元,单元名取自该文件名。-a 2 选择令牌认证,因此生成的每个方法都会发送 Authorization: Bearer。同一个可执行文件在不带参数启动时是一个图形向导,成功时退出码为 0,输入文件有问题为 5,输出文件有问题为 6,文档无法转换为有效的 OpenAPI 3 文档时为 7。

把生成的 .pas 加入项目并写进 uses 子句。没有需要安装的组件,因为 sgcOpenAPI 不注册任何组件,也不提供设计期包。

列出您的仓库

GitHub 的操作 id 里带有斜杠和连字符,例如 repos/list-for-authenticated-user。这些字符不能出现在 Pascal 标识符中,生成器会把它们去掉,方法最终写作 reposlistforauthenticateduser。

uses
  github;   // 刚刚生成的单元

procedure TfrmGitHub.btnReposClick(Sender: TObject);
var
  oResponse: TsgcOpenAPI_reposlistforauthenticateduser_Response;
  oRepo: TsgcOpenAPI_repository_Class;
begin
  GetOpenAPIClient.Authentication.Token.BearerToken := txtToken.Text;

  oResponse := GetOpenAPIClient.reposlistforauthenticateduser(
    'private', 'owner', 'all', 'full_name', '', 100, 1);
  try
    if oResponse.IsSuccessful then
    begin
      for oRepo in oResponse.Successful.Items do
        memoLog.Lines.Add(oRepo.Full_name + '  ' + oRepo.Description);
    end
    else
      memoLog.Lines.Add(IntToStr(oResponse.ResponseCode) + ' ' +
        oResponse.ResponseError);
  finally
    oResponse.Free;
  end;
end;

返回数组的端点,其响应的 Successful 是 TsgcOpenAPIArray 的后代,带有类型化的 Items,这里是 TArray<TsgcOpenAPI_repository_Class>。基础 URL 来自 servers 条目,因此生成的构造函数已经设好 https://api.github.com。分页没有被隐藏:aPer_page 和 aPage 就是普通参数,翻页由您自己循环完成。

如果全小写的名称让您不适应,用 -m 1 生成,方法名就改用操作摘要,或者用 -m 2 用端点命名。

创建议题并列出拉取请求

路径参数按文档声明的顺序排在参数列表前面。请求体是一个字符串,原因见下文。

var
  oIssue: TsgcOpenAPI_issuescreate_Response;
  oPulls: TsgcOpenAPI_pullslist_Response;
begin
  oIssue := GetOpenAPIClient.issuescreate('octocat', 'Hello-World',
    '{"title":"Memory leak in the HTTP/2 reader",' +
    '"body":"Repro steps: ...","labels":["bug","http2"]}');
  try
    if oIssue.IsSuccessful then
      memoLog.Lines.Add('filed issue #' +
        IntToStr(oIssue.Successful.Number) + ' ' + oIssue.Successful.Html_url)
    else
      memoLog.Lines.Add(oIssue.Error422._message);
  finally
    oIssue.Free;
  end;

  oPulls := GetOpenAPIClient.pullslist('octocat', 'Hello-World',
    'open', 'updated');
  try
    memoLog.Lines.Add(IntToStr(oPulls.ResponseCode));
  finally
    oPulls.Free;
  end;
end;

每个响应类都带有 Successful,以及文档声明的每个状态码各一个属性,因此调用失败时可以读取 Error304、Error401、Error403 和 Error422。GitHub 用具名模式描述的状态会变成一个类,什么都没描述的状态则变成普通字符串。错误属性按需创建,因此它永远不为 nil,您应该检查 IsSuccessful,而不是检查对象本身。

_message 里的下划线不是笔误。message 是生成器需要转义的 68 个 Pascal 保留字之一,因此同名的模式字段会带一个前导下划线。type、object、default、index 以及名单上的其余保留字也是如此,它们都在 GitHub 的模式里出现过。

生成的单元包含什么

单元是这份描述的镜像。没有任何人工筛选,因此 GitHub 记录过的内容都在,GitHub 没有写的内容也就没有。

每个有文档记录的操作

1,225 个方法,涵盖仓库和内容、议题和拉取请求、Actions 和检查运行、包、组织和团队、GitHub Apps、代码扫描以及其余接口。

每个方法一个响应类

每一个都继承自 TsgcOpenAPIResponse,并继承 IsSuccessful(状态码 200 到 299 时为 true),以及 ResponseCode 和 ResponseError。

3,250 个模型类

TsgcOpenAPI_repository_Class、TsgcOpenAPI_issue_Class、TsgcOpenAPI_basic_error_Class、TsgcOpenAPI_validation_error_Class,以及 components 部分中的其他每一个模式。

标签作为注释

GitHub 的标签会输出为注释,把方法在同一个客户端类里分组。它们不会变成独立的类,因此一切都挂在 GetOpenAPIClient 之下。

来自规范的文档

GitHub 自己的描述会作为 Pascal 注释出现在每个方法和属性上方,因此 IDE 会在您使用它们的地方显示出来。

Enterprise Server 同样适用

ghes-3.x 描述以同样的方式生成。如果两边都要访问,就为每个目标各保留一个生成的单元。

四件值得知道的事

这四点都来自对当前描述的一次真实生成运行。

单元非常大

大约 274,000 行、12 MB,是这些页面上我们生成过的公开规范里最大的一个。它在两秒内编译完成,但 IDE 编辑器处理这么大的文件会变慢。-x 会剔除您以 "VERB endpoint" 形式列出的操作,随后 -p 移除剩余操作都不再用到的类。

大多数请求体是字符串

有 343 个操作声明了 application/json 请求体,但其中几乎全部都把它描述为匿名的内联对象,而不是具名模式。内联对象没有可命名的类,因此参数是 const aBody: string,JSON 由您自己拼。少数引用具名模式的操作确实会得到一个类型化的类。

273 条警告,值得一读

大多数与没有判别符映射的组合有关,此时生成的类为每个分支保留一个成员。少数几条报告文档未能解析的 $ref,还有几条报告某个操作声明了两个成功状态,而其中只有一个被生成。生成器会指明是哪一个,而不是默默做选择。

速率限制和应用令牌由您自己处理

生成的客户端就是一个忠实的 HTTP 客户端,仅此而已。它不缓存 ETag 值,不在 403 时重试,也不刷新 GitHub App 的安装令牌。请读取 ResponseCode,用 OnBeforeRequest 添加条件请求头,并用单元中已有的 apps 方法签发安装令牌。

来自博客

OpenAPI Delphi 解析器

读取器如何处理真实的规范,包括大部分警告背后的那些组合关键字。

阅读文章 →

OpenAPI 客户端 + 解析器

介绍生成的客户端及其所基于的读取器的配套文章。

阅读文章 →

sgcOpenAPI 2026.6

当前版本的发行说明,包含生成器选项和读取器变更。

阅读文章 →
超值之选:All-AccesseSeGeCe 全部产品,含高级支持,每年 €1,059 起。
查看 All-Access 价格

今天就构建您的 GitHub 自动化

sgcOpenAPI 随附读取器、代码生成器、OpenAPI 服务器,以及 Amazon、Azure、Google 和 Microsoft 的预构建 SDK。一个产品,三个层级,按席位计价而不是按功能计价。