sgcOpenAPI vs Swagger Codegen — Generate Delphi Clients Faster

· Reviews

The problem: most modern APIs ship an OpenAPI spec, not a Delphi SDK

If you have ever integrated a modern REST API in Delphi, the workflow probably looked like this: read the docs, hand-write a wrapper around TIdHTTP or TNetHTTPClient, paste request bodies into string literals, parse responses with TJSONObject, fight with TDateTime serialisation, repeat for every endpoint. It works but it does not scale. The API has 80 endpoints, you wrap 8 of them, the vendor adds 10 more next month, and your wrapper rots.

The promise of OpenAPI (formerly Swagger) is that the vendor publishes a machine-readable description — one YAML or JSON file — and a generator turns it into a typed client in your language of choice. For most languages this works extremely well: openapi-generator and swagger-codegen produce idiomatic clients for Python, TypeScript, Go, Java, C#, Rust and many others.

For Delphi the story has historically been less smooth. This post compares the two main options as of 2026 — the long-standing open-source swagger-codegen Delphi generator and the native commercial sgcOpenAPI from eSeGeCe — and shows what each produces from the same input spec.

About swagger-codegen and openapi-generator

The Swagger project, now under the SmartBear umbrella, ships swagger-codegen. After a community fork in 2018 a parallel project, openapi-generator, became the de facto standard for many languages. Both tools support a long list of target languages via Mustache templates. A Delphi generator (delphi in swagger-codegen, plus community templates) exists, but it has always been a second-tier target maintained by occasional volunteers.

As of writing, the Delphi template in openapi-generator generates code that compiles on older Delphi versions but has known issues on modern Delphi (D11/D12/D13): incorrect handling of nullable fields, missing {$IFDEF} guards for newer RTL, no support for OpenAPI 3.1, no streaming response support, and a runtime that depends on a particular HTTP client library version. Several of the long-standing GitHub issues against the Delphi generator have been open for years. Your mileage will vary by spec.

About sgcOpenAPI

sgcOpenAPI is a native Delphi tool from eSeGeCe. It parses OpenAPI 3.0 (and now 3.1) specifications and emits Delphi units that follow sgc naming conventions: Tsgc[Api]Client for the client, Tsgc[Api]_[Model] for each schema object, and one method per operation. The generated code uses TsgcHTTPComponentClient from sgcWebSockets as the transport, so authentication, retry, TLS and HTTP/2 are inherited for free.

Because the generator is itself written in Delphi, it can be embedded in a Delphi tool, run from the command line, or invoked from a build script. The output is plain .pas files with no runtime dependency beyond sgcWebSockets — no JVM, no Node, no Python, no template engine.

Feature comparison

Featureswagger-codegen / openapi-generator (Delphi target)sgcOpenAPI
OpenAPI 2.0 (Swagger)YesYes
OpenAPI 3.0Yes (openapi-generator)Yes
OpenAPI 3.1Limited as of writingYes
Runtime requirementJava 11+ to run the generatorNone (native Delphi exe)
Target Delphi versionsBest effort on D10.x, often broken on D11+ as of writingD7 through D13
HTTP backendIndy by default in current Delphi templatessgcHTTPComponentClient (Indy / ICS / SChannel, plus HTTP/2)
Async / streaming responsesLimitedYes
OAuth2 / API key / bearer authPartialYes, native components
Polymorphism (oneOf, allOf, discriminator)LimitedYes
Nullable fieldsInconsistentYes (TsgcNullable<T>)
File upload / multipartPartialYes
Server stub generationYes (other languages mostly)Yes (Delphi server stubs with sgcWebSocketHTTPServer)
LicenseOpen source (Apache 2.0)Commercial

Workflow comparison

swagger-codegen workflow

  1. Install Java 11 or newer.
  2. Download the openapi-generator-cli JAR.
  3. Run java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out.
  4. Open the generated .pas files in your IDE. Add the Indy runtime path. Fix any compilation issues for your Delphi version. Patch nullable handling. Re-run after every spec change.
  5. The generated client depends on a separate runtime support unit shipped by the template. You ship that unit with your project.

sgcOpenAPI workflow

  1. Open sgcOpenAPI IDE or call the CLI: sgcOpenAPI.exe -i spec.yaml -o ./out.
  2. Open the generated unit in the IDE. It uses TsgcHTTPComponentClient which you already have if you use sgcWebSockets.
  3. Drop the generated client component on a form, set the base URL and credentials, and call the typed methods.

Side-by-side: a generated GET /users/{id} method

Same OpenAPI fragment, both tools, identical operation. Names of helpers and exact formatting are stylised slightly for clarity but the differences in approach are real.

swagger-codegen (Delphi target, simplified)

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.

Differences worth noting:

Server stubs

Both tools can also generate server-side code, but the Delphi server templates in openapi-generator are minimal as of writing. sgcOpenAPI generates a TsgcWebSocketHTTPServer-based handler with one virtual method per operation, request validation, response shaping and a built-in OpenAPI explorer endpoint. For internal services where you want a single Delphi project to expose the API and a Delphi client to consume it, the round-trip is very short.

When swagger-codegen is still the right choice

When sgcOpenAPI saves real time

Closing thoughts

Code generation from OpenAPI is one of those productivity wins that compounds over the life of a project — provided the generator keeps pace with the spec and with your Delphi version. swagger-codegen / openapi-generator are excellent multi-language tools, but their Delphi target has historically been treated as best-effort. sgcOpenAPI is a focused, native Delphi alternative that delivers compilable, idiomatic, full-feature OpenAPI 3.0 / 3.1 clients (and server stubs) without a Java dependency and without the manual patching cycle. For most Delphi teams already integrating REST APIs, it pays for itself the first time a vendor updates their spec.