sgcOpenAPI vs Swagger Codegen——更快生成 Delphi 客户端

· 评测

问题:大多数现代 API 提供 OpenAPI 规范,而非 Delphi SDK

如果您曾经在 Delphi 中集成过现代 REST API,工作流可能是这样的:阅读文档、围绕 TIdHTTPTNetHTTPClient 手写包装器、将请求体粘贴到字符串字面值中、用 TJSONObject 解析响应、与 TDateTime 序列化作斗争、对每个端点重复这一过程。它可以工作,但无法扩展。API 有 80 个端点,您包装了 8 个,供应商下个月添加了 10 个,您的包装器就会腐烂。

OpenAPI(以前称为 Swagger)的承诺是供应商发布一个机器可读的描述——一个 YAML 或 JSON 文件——而生成器将其转换为您选择的语言中的类型化客户端。对于大多数语言,这非常有效:openapi-generatorswagger-codegen 为 Python、TypeScript、Go、Java、C#、Rust 和许多其他语言生成符合习惯的客户端。

对于 Delphi,这一过程历来不那么顺畅。本文比较了 2026 年的两个主要选项——长期存在的开源 swagger-codegen Delphi 生成器和 eSeGeCe 的原生商业 sgcOpenAPI——并展示了它们从相同输入规范生成的内容。

关于 swagger-codegen 和 openapi-generator

Swagger 项目现在在 SmartBear 旗下,提供 swagger-codegen。在 2018 年社区分叉后,一个并行项目 openapi-generator 成为许多语言事实上的标准。两个工具都通过 Mustache 模板支持一长串目标语言。Delphi 生成器(swagger-codegen 中的 delphi,加上社区模板)存在,但它一直是二线目标,由偶尔的志愿者维护。

截至撰写本文时,openapi-generator 中的 Delphi 模板生成的代码可在较旧的 Delphi 版本上编译,但在现代 Delphi (D11/D12/D13) 上存在已知问题:可空字段处理不正确、缺少较新 RTL 的 {$IFDEF} 守卫、不支持 OpenAPI 3.1、不支持流式响应,以及依赖于特定 HTTP 客户端库版本的运行时。针对 Delphi 生成器的几个长期存在的 GitHub 问题已经打开多年。您的体验会因规范而异。

关于 sgcOpenAPI

sgcOpenAPI 是 eSeGeCe 的原生 Delphi 工具。它解析 OpenAPI 3.0(现在是 3.1)规范并发出遵循 sgc 命名约定的 Delphi 单元:客户端的 Tsgc[Api]Client、每个模式对象的 Tsgc[Api]_[Model],以及每个操作一个方法。生成的代码使用 sgcWebSockets 的 TsgcHTTPComponentClient 作为传输,因此身份验证、重试、TLS 和 HTTP/2 都免费继承。

由于生成器本身是用 Delphi 编写的,它可以嵌入到 Delphi 工具中、从命令行运行,或从构建脚本调用。输出是普通的 .pas 文件,除 sgcWebSockets 之外没有运行时依赖——没有 JVM、没有 Node、没有 Python、没有模板引擎。

功能比较

功能swagger-codegen / openapi-generator (Delphi 目标)sgcOpenAPI
OpenAPI 2.0 (Swagger)
OpenAPI 3.0是 (openapi-generator)
OpenAPI 3.1撰写时有限
运行时要求需要 Java 11+ 来运行生成器无(原生 Delphi exe)
目标 Delphi 版本D10.x 上尽力而为,撰写时在 D11+ 上经常损坏D7 至 D13
HTTP 后端当前 Delphi 模板中默认为 IndysgcHTTPComponentClient(Indy / ICS / SChannel,加上 HTTP/2)
异步/流式响应有限
OAuth2 / API 密钥 / bearer 身份验证部分是,原生组件
多态性(oneOfallOfdiscriminator有限
可空字段不一致是 (TsgcNullable<T>)
文件上传/多部分部分
服务器存根生成是(主要是其他语言)是(带 sgcWebSocketHTTPServer 的 Delphi 服务器存根)
许可开源 (Apache 2.0)商业

工作流比较

swagger-codegen 工作流

  1. 安装 Java 11 或更高版本。
  2. 下载 openapi-generator-cli JAR。
  3. 运行 java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out
  4. 在 IDE 中打开生成的 .pas 文件。添加 Indy 运行时路径。修复 Delphi 版本的任何编译问题。修补可空处理。每次规范更改后重新运行。
  5. 生成的客户端依赖于模板提供的单独的运行时支持单元。您将该单元与项目一起发布。

sgcOpenAPI 工作流

  1. 打开 sgcOpenAPI IDE 或调用 CLI:sgcOpenAPI.exe -i spec.yaml -o ./out
  2. 在 IDE 中打开生成的单元。它使用 TsgcHTTPComponentClient,如果您使用 sgcWebSockets,您已经拥有它。
  3. 将生成的客户端组件放在窗体上,设置基础 URL 和凭据,并调用类型化方法。

并排:生成的 GET /users/{id} 方法

相同的 OpenAPI 片段、两种工具、相同的操作。辅助方法名称和确切格式略经美化以提高清晰度,但方法上的差异是真实的。

swagger-codegen(Delphi 目标,简化)

function TUsersApi.GetUserById(const Id: Int64): TUser;
var
  HttpRequest: TIdHTTP;
  Path, Response: string;
  JsonValue: TJSONValue;
begin
  Path := StringReplace(BasePath + '/users/{id}', '{id}', IntToStr(Id), [rfReplaceAll]);
  HttpRequest := TIdHTTP.Create(nil);
  try
    HttpRequest.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FApiKey);
    Response := HttpRequest.Get(Path);
  finally
    HttpRequest.Free;
  end;
  JsonValue := TJSONObject.ParseJSONValue(Response);
  try
    Result := TUser.Create;
    Result.Id := (JsonValue as TJSONObject).GetValue<Int64>('id');
    Result.Name := (JsonValue as TJSONObject).GetValue<string>('name');
    // ... nullable fields handled inconsistently ...
  finally
    JsonValue.Free;
  end;
end;

sgcOpenAPI

function TsgcUsersApiClient.GetUserById(const aId: Int64): TsgcUser;
var
  vResponse: TsgcAPIResponse;
begin
  Result := nil;
  vResponse := DoGet(Format('/users/%d', [aId]));
  Try
    if vResponse.StatusCode = 200 then
      Result := TsgcUser.FromJSON(vResponse.Content);
  Finally
    vResponse.Free;
  End;
end;

// TsgcUser is generated with typed nullable fields:
//   property Id: Int64 read FId write FId;
//   property Name: string read FName write FName;
//   property Email: TsgcNullable<string> read FEmail write FEmail;
//   property CreatedAt: TDateTime read FCreatedAt write FCreatedAt;
//
// Authentication, retry, HTTP/2, TLS are configured on the
// underlying TsgcHTTPComponentClient once, not per-method.

值得注意的差异:

服务器存根

两个工具都可以生成服务器端代码,但截至撰写本文时,openapi-generator 中的 Delphi 服务器模板很简单。sgcOpenAPI 生成基于 TsgcWebSocketHTTPServer 的处理程序,每个操作一个虚拟方法、请求验证、响应塑形和内置的 OpenAPI 浏览器端点。对于希望单个 Delphi 项目公开 API 并由 Delphi 客户端消费它的内部服务,往返非常短。

swagger-codegen 仍然是正确选择的时候

sgcOpenAPI 节省真正时间的时候

结束思考

从 OpenAPI 生成代码是那种在项目生命周期中累积的生产力胜利之一——前提是生成器跟上规范和您的 Delphi 版本。swagger-codegen / openapi-generator 是出色的多语言工具,但它们的 Delphi 目标在历史上被视为尽力而为。sgcOpenAPI 是一个专注的、原生的 Delphi 替代品,无需 Java 依赖且无需手动修补周期,即可交付可编译的、符合习惯的、完整功能的 OpenAPI 3.0 / 3.1 客户端(和服务器存根)。对于已经集成 REST API 的大多数 Delphi 团队,它在供应商首次更新其规范时就为自己付清成本。