sgcOpenAPI vs Swagger Codegen — Genera clientes Delphi más rápido

· Reseñas

El problema: la mayoría de APIs modernas distribuyen una spec OpenAPI, no un SDK Delphi

Si alguna vez has integrado una API REST moderna en Delphi, el flujo probablemente se vio así: lees los docs, escribes a mano un wrapper alrededor de TIdHTTP o TNetHTTPClient, pegas cuerpos de petición en literales string, parseas respuestas con TJSONObject, peleas con la serialización de TDateTime, repites por cada endpoint. Funciona pero no escala. La API tiene 80 endpoints, envuelves 8, el fabricante añade 10 más el mes que viene y tu wrapper se pudre.

La promesa de OpenAPI (antes Swagger) es que el fabricante publica una descripción legible por máquina — un único archivo YAML o JSON — y un generador la convierte en un cliente tipado en tu lenguaje de elección. Para la mayoría de lenguajes esto funciona extremadamente bien: openapi-generator y swagger-codegen producen clientes idiomáticos para Python, TypeScript, Go, Java, C#, Rust y muchos otros.

Para Delphi la historia ha sido históricamente menos fluida. Este post compara las dos opciones principales en 2026 — el viejo conocido open-source generador Delphi de swagger-codegen y el nativo comercial sgcOpenAPI de eSeGeCe — y muestra qué produce cada uno desde la misma spec de entrada.

Sobre swagger-codegen y openapi-generator

El proyecto Swagger, ahora bajo el paraguas de SmartBear, distribuye swagger-codegen. Tras un fork de la comunidad en 2018 un proyecto paralelo, openapi-generator, se convirtió en el estándar de facto para muchos lenguajes. Ambas herramientas soportan una larga lista de lenguajes destino vía plantillas Mustache. Existe un generador Delphi (delphi en swagger-codegen, más plantillas comunitarias), pero siempre ha sido un objetivo de segunda fila mantenido por voluntarios ocasionales.

Al momento de escribir, la plantilla Delphi en openapi-generator genera código que compila en versiones antiguas de Delphi pero tiene problemas conocidos en Delphi moderno (D11/D12/D13): manejo incorrecto de campos nullable, falta de guardas {$IFDEF} para la RTL más reciente, sin soporte para OpenAPI 3.1, sin soporte de respuestas en streaming y un runtime que depende de una versión concreta de la librería cliente HTTP. Varios de los issues de GitHub abiertos contra el generador Delphi llevan años abiertos. Tu kilometraje variará por spec.

Sobre sgcOpenAPI

sgcOpenAPI es una herramienta Delphi nativa de eSeGeCe. Parsea especificaciones OpenAPI 3.0 (y ahora 3.1) y emite units Delphi que siguen las convenciones de nomenclatura sgc: Tsgc[Api]Client para el cliente, Tsgc[Api]_[Model] para cada objeto de esquema y un método por operación. El código generado usa TsgcHTTPComponentClient de sgcWebSockets como transporte, así que autenticación, reintento, TLS y HTTP/2 se heredan gratis.

Como el generador está él mismo escrito en Delphi, puede embeberse en una herramienta Delphi, ejecutarse desde la línea de comandos o invocarse desde un script de build. La salida son archivos .pas planos sin dependencia de runtime más allá de sgcWebSockets — sin JVM, sin Node, sin Python, sin motor de plantillas.

Comparación de funciones

Funciónswagger-codegen / openapi-generator (target Delphi)sgcOpenAPI
OpenAPI 2.0 (Swagger)
OpenAPI 3.0Sí (openapi-generator)
OpenAPI 3.1Limitado al momento de escribir
Requisito de runtimeJava 11+ para ejecutar el generadorNinguno (exe Delphi nativo)
Versiones Delphi destinoBest effort en D10.x, a menudo roto en D11+ al momento de escribirD7 hasta D13
Backend HTTPIndy por defecto en plantillas Delphi actualessgcHTTPComponentClient (Indy / ICS / SChannel, más HTTP/2)
Respuestas async / streamingLimitado
OAuth2 / API key / bearer authParcialSí, componentes nativos
Polimorfismo (oneOf, allOf, discriminator)Limitado
Campos nullableInconsistenteSí (TsgcNullable<T>)
Subida de archivos / multipartParcial
Generación de stub servidorSí (otros lenguajes mayormente)Sí (stubs servidor Delphi con sgcWebSocketHTTPServer)
LicenciaOpen source (Apache 2.0)Comercial

Comparación de flujo de trabajo

Flujo swagger-codegen

  1. Instala Java 11 o superior.
  2. Descarga el JAR openapi-generator-cli.
  3. Ejecuta java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out.
  4. Abre los archivos .pas generados en tu IDE. Añade la ruta de runtime de Indy. Arregla cualquier problema de compilación para tu versión de Delphi. Parchea el manejo de nullable. Vuelve a ejecutar tras cada cambio de spec.
  5. El cliente generado depende de una unit de soporte de runtime separada distribuida por la plantilla. Entregas esa unit con tu proyecto.

Flujo sgcOpenAPI

  1. Abre el IDE de sgcOpenAPI o llama al CLI: sgcOpenAPI.exe -i spec.yaml -o ./out.
  2. Abre la unit generada en el IDE. Usa TsgcHTTPComponentClient que ya tienes si usas sgcWebSockets.
  3. Arrastra el componente cliente generado a un form, establece la URL base y las credenciales y llama a los métodos tipados.

Lado a lado: un método GET /users/{id} generado

El mismo fragmento OpenAPI, ambas herramientas, operación idéntica. Los nombres de helpers y el formato exacto están ligeramente estilizados para claridad pero las diferencias de enfoque son reales.

swagger-codegen (target Delphi, simplificado)

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.

Diferencias que merece la pena destacar:

Stubs de servidor

Ambas herramientas pueden también generar código del lado servidor, pero las plantillas Delphi de servidor en openapi-generator son mínimas al momento de escribir. sgcOpenAPI genera un manejador basado en TsgcWebSocketHTTPServer con un método virtual por operación, validación de petición, modelado de respuesta y un endpoint integrado de explorador OpenAPI. Para servicios internos donde quieres que un único proyecto Delphi exponga la API y un cliente Delphi la consuma, el round-trip es muy corto.

Cuándo swagger-codegen sigue siendo la elección correcta

Cuándo sgcOpenAPI ahorra tiempo real

Reflexiones finales

La generación de código a partir de OpenAPI es una de esas victorias de productividad que se acumulan durante la vida de un proyecto — siempre que el generador siga el ritmo de la spec y de tu versión Delphi. swagger-codegen / openapi-generator son excelentes herramientas multi-lenguaje, pero su target Delphi históricamente se ha tratado como best-effort. sgcOpenAPI es una alternativa nativa Delphi focalizada que entrega clientes OpenAPI 3.0 / 3.1 (y stubs servidor) compilables, idiomáticos y con todas las funciones, sin dependencia de Java y sin el ciclo de parcheado manual. Para la mayoría de equipos Delphi que ya integran APIs REST, se paga sólo la primera vez que un fabricante actualiza su spec.