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ón | swagger-codegen / openapi-generator (target Delphi) | sgcOpenAPI |
|---|---|---|
| OpenAPI 2.0 (Swagger) | Sí | Sí |
| OpenAPI 3.0 | Sí (openapi-generator) | Sí |
| OpenAPI 3.1 | Limitado al momento de escribir | Sí |
| Requisito de runtime | Java 11+ para ejecutar el generador | Ninguno (exe Delphi nativo) |
| Versiones Delphi destino | Best effort en D10.x, a menudo roto en D11+ al momento de escribir | D7 hasta D13 |
| Backend HTTP | Indy por defecto en plantillas Delphi actuales | sgcHTTPComponentClient (Indy / ICS / SChannel, más HTTP/2) |
| Respuestas async / streaming | Limitado | Sí |
| OAuth2 / API key / bearer auth | Parcial | Sí, componentes nativos |
Polimorfismo (oneOf, allOf, discriminator) | Limitado | Sí |
| Campos nullable | Inconsistente | Sí (TsgcNullable<T>) |
| Subida de archivos / multipart | Parcial | Sí |
| Generación de stub servidor | Sí (otros lenguajes mayormente) | Sí (stubs servidor Delphi con sgcWebSocketHTTPServer) |
| Licencia | Open source (Apache 2.0) | Comercial |
Comparación de flujo de trabajo
Flujo swagger-codegen
- Instala Java 11 o superior.
- Descarga el JAR
openapi-generator-cli. - Ejecuta
java -jar openapi-generator-cli.jar generate -i spec.yaml -g delphi -o ./out. - Abre los archivos
.pasgenerados 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. - El cliente generado depende de una unit de soporte de runtime separada distribuida por la plantilla. Entregas esa unit con tu proyecto.
Flujo sgcOpenAPI
- Abre el IDE de sgcOpenAPI o llama al CLI:
sgcOpenAPI.exe -i spec.yaml -o ./out. - Abre la unit generada en el IDE. Usa
TsgcHTTPComponentClientque ya tienes si usas sgcWebSockets. - 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:
- sgcOpenAPI separa el transporte (configuración a nivel de componente) de las operaciones (métodos tipados), así que auth, reintento y TLS se configuran una sola vez.
- Los campos nullable usan un envoltorio tipado
TsgcNullable<T>que distingue “ausente”, “null” y “valor” — emparejando con la semántica de OpenAPI 3.x. - Los campos de fecha/hora usan
TDateTimereal con el parser ISO 8601 correcto, no un string que parseas después. - El cliente generado usa el componente HTTP de sgcWebSockets, que soporta HTTP/2 de forma transparente si el servidor lo anuncia vía ALPN.
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
- Ya estás estandarizado en
openapi-generatoren muchos lenguajes y quieres una sola herramienta en tu pipeline CI. - Tu spec es pequeña y estable y no necesitas funciones de OpenAPI 3.1.
- Te sientes cómodo parcheando el Delphi generado para encajar con tu versión objetivo.
- No puedes usar software comercial por razones de licencia.
Cuándo sgcOpenAPI ahorra tiempo real
- Estás en una versión Delphi actual (D11 / D12 / D13) donde la plantilla Delphi de swagger-codegen está crujiente al momento de escribir.
- Tu spec usa OpenAPI 3.1,
oneOf/discriminator, campos nullable, subida de archivos o streaming async. - Ya usas sgcWebSockets y quieres un modelo de componente consistente y una única pila HTTP.
- Necesitas que HTTP/2, TLS, OAuth2 y reintento “simplemente funcionen” sin reescribir el cliente generado.
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.