sgcOpenAPI vs Swagger Codegen — Genereer Delphi-clients sneller

· Reviews

Het probleem: de meeste moderne API’s leveren een OpenAPI-spec, geen Delphi-SDK

Als je ooit een moderne REST-API in Delphi hebt geintegreerd, zag de workflow er waarschijnlijk zo uit: docs lezen, met de hand een wrapper rond TIdHTTP of TNetHTTPClient schrijven, request-bodies in string literals plakken, antwoorden parsen met TJSONObject, vechten met TDateTime-serialisatie, herhalen voor elke endpoint. Het werkt, maar het schaalt niet. De API heeft 80 endpoints, je wrapt er 8, de leverancier voegt er volgende maand 10 toe, en je wrapper vergaat.

De belofte van OpenAPI (voorheen Swagger) is dat de leverancier een machine-leesbare beschrijving publiceert — een YAML- of JSON-bestand — en een generator zet dat om in een typed client in de taal van je keuze. Voor de meeste talen werkt dit uitstekend: openapi-generator en swagger-codegen produceren idiomatische clients voor Python, TypeScript, Go, Java, C#, Rust en vele andere.

Voor Delphi is dat verhaal historisch gezien minder soepel geweest. Dit bericht vergelijkt de twee belangrijkste opties per 2026 — de al lang bestaande open-source swagger-codegen Delphi-generator en de native commerciele sgcOpenAPI van eSeGeCe — en laat zien wat elk produceert uit dezelfde input-spec.

Over swagger-codegen en openapi-generator

Het Swagger-project, nu onder de SmartBear-paraplu, levert swagger-codegen. Na een community-fork in 2018 werd een parallel project, openapi-generator, de facto standaard voor veel talen. Beide tools ondersteunen een lange lijst doel-talen via Mustache templates. Een Delphi-generator (delphi in swagger-codegen, plus community templates) bestaat, maar is altijd een tweederangs doel geweest, onderhouden door incidentele vrijwilligers.

Op het moment van schrijven genereert het Delphi-template in openapi-generator code die compileert op oudere Delphi-versies maar bekende problemen heeft op moderne Delphi (D11/D12/D13): onjuiste afhandeling van nullable velden, ontbrekende {$IFDEF}-guards voor nieuwere RTL, geen ondersteuning voor OpenAPI 3.1, geen streaming response-ondersteuning, en een runtime die afhangt van een specifieke HTTP-client bibliotheekversie. Diverse al lang bestaande GitHub-issues tegen de Delphi-generator staan al jaren open. Je ervaring zal varieren per spec.

Over sgcOpenAPI

sgcOpenAPI is een native Delphi-tool van eSeGeCe. Het parset OpenAPI 3.0 (en nu 3.1) specificaties en levert Delphi-units op die de sgc-naamgevingsconventies volgen: Tsgc[Api]Client voor de client, Tsgc[Api]_[Model] voor elk schema-object, en een methode per operation. De gegenereerde code gebruikt TsgcHTTPComponentClient uit sgcWebSockets als transport, dus authenticatie, retry, TLS en HTTP/2 worden gratis geerfd.

Omdat de generator zelf in Delphi is geschreven, kan hij worden ingebed in een Delphi-tool, vanaf de command line worden uitgevoerd of vanuit een build script worden aangeroepen. De output is gewone .pas-bestanden zonder runtime-afhankelijkheid buiten sgcWebSockets — geen JVM, geen Node, geen Python, geen template engine.

Feature-vergelijking

Featureswagger-codegen / openapi-generator (Delphi-target)sgcOpenAPI
OpenAPI 2.0 (Swagger)JaJa
OpenAPI 3.0Ja (openapi-generator)Ja
OpenAPI 3.1Beperkt op moment van schrijvenJa
Runtime-vereisteJava 11+ om de generator te draaienGeen (native Delphi-exe)
Doel-Delphi-versiesBest effort op D10.x, vaak gebroken op D11+ op moment van schrijvenD7 t/m D13
HTTP-backendIndy standaard in huidige Delphi-templatessgcHTTPComponentClient (Indy / ICS / SChannel, plus HTTP/2)
Async / streaming responsesBeperktJa
OAuth2 / API key / bearer authGedeeltelijkJa, native componenten
Polymorfie (oneOf, allOf, discriminator)BeperktJa
Nullable veldenInconsistentJa (TsgcNullable<T>)
Bestandsupload / multipartGedeeltelijkJa
Server stub-generatieJa (vooral andere talen)Ja (Delphi server stubs met sgcWebSocketHTTPServer)
LicentieOpen source (Apache 2.0)Commercieel

Workflow-vergelijking

swagger-codegen workflow

  1. Installeer Java 11 of nieuwer.
  2. Download de openapi-generator-cli JAR.
  3. Voer java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out uit.
  4. Open de gegenereerde .pas-bestanden in je IDE. Voeg het Indy-runtime-pad toe. Los eventuele compilatieproblemen voor je Delphi-versie op. Patch nullable-afhandeling. Voer opnieuw uit na elke spec-wijziging.
  5. De gegenereerde client hangt af van een aparte runtime support-unit die door het template wordt geleverd. Je verzendt die unit mee met je project.

sgcOpenAPI workflow

  1. Open de sgcOpenAPI-IDE of roep de CLI aan: sgcOpenAPI.exe -i spec.yaml -o ./out.
  2. Open de gegenereerde unit in de IDE. Hij gebruikt TsgcHTTPComponentClient die je al hebt als je sgcWebSockets gebruikt.
  3. Plaats de gegenereerde client-component op een formulier, stel de base-URL en credentials in, en roep de typed methodes aan.

Side-by-side: een gegenereerde GET /users/{id}-methode

Hetzelfde OpenAPI-fragment, beide tools, identieke operation. Namen van helpers en exacte formattering zijn licht gestileerd voor duidelijkheid maar de verschillen in aanpak zijn reeel.

swagger-codegen (Delphi-target, vereenvoudigd)

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.

Verschillen die het noemen waard zijn:

Server stubs

Beide tools kunnen ook server-side code genereren, maar de Delphi server-templates in openapi-generator zijn op moment van schrijven minimaal. sgcOpenAPI genereert een op TsgcWebSocketHTTPServer gebaseerde handler met een virtuele methode per operation, request-validatie, response-shaping en een ingebouwd OpenAPI-explorer-endpoint. Voor interne services waar je een enkel Delphi-project de API wilt laten exposen en een Delphi-client wilt laten consumeren, is de round-trip zeer kort.

Wanneer swagger-codegen nog de juiste keuze is

Wanneer sgcOpenAPI echte tijd bespaart

Afsluitende gedachten

Code-generatie vanuit OpenAPI is een van die productiviteitswinsten die zich opstapelt over de levensduur van een project — mits de generator de spec en je Delphi-versie bijhoudt. swagger-codegen / openapi-generator zijn uitstekende multi-language tools, maar hun Delphi-target is historisch als best-effort behandeld. sgcOpenAPI is een gerichte, native Delphi-alternatief dat compileerbare, idiomatische, full-feature OpenAPI 3.0 / 3.1-clients (en server stubs) levert zonder Java-afhankelijkheid en zonder de handmatige patch-cyclus. Voor de meeste Delphi-teams die al REST-API’s integreren, verdient het zich de eerste keer terug dat een leverancier zijn spec bijwerkt.