openapi-examples-generator: ejemplos automáticos para tus contratos OpenAPI

Un contrato OpenAPI puede estar impecablemente modelado —cada esquema, cada propiedad, cada tipo en su sitio— y aun así ofrecer una experiencia pobre a quien lo consume. ¿El motivo? Le faltan ejemplos. Sin un solo example, el botón «Try it out» de Swagger UI aparece vacío, los mocks devuelven cadenas genéricas como "string" y la documentación generada resulta abstracta justo donde debería ser concreta. Escribir esos ejemplos a mano es tedioso, se nos olvida y, lo peor, se desincroniza del esquema en cuanto el contrato evoluciona.

Desde la APIAddicts Foundation publicamos openapi-examples-generator, una herramienta de línea de comandos de código abierto que resuelve exactamente ese problema: inyecta ejemplos realistas en tu documento OpenAPI o Swagger a partir de la propia estructura de sus esquemas, sin que tengas que teclear un solo valor a mano. En este artículo repasamos qué hace, por qué importa, cómo se usa y —lo más interesante para quien vive del contract-first— dónde y cómo inyecta los ejemplos para no romper el contrato.

El problema: esquemas sin ejemplos

La mayoría de contratos nacen del modelo de datos: definimos components.schemas (u definitions en Swagger 2.0), describimos parámetros, cuerpos de petición y respuestas… y ahí paramos. El esquema es correcto y validable, pero está «mudo»: no contiene ejemplos. Las consecuencias son conocidas por cualquiera que haya publicado una API:

  • Documentación menos útil. Portales como Swagger UI o Redoc muestran la forma del dato, pero no un valor representativo. El lector tiene que imaginarse cómo se ve una respuesta real.
  • «Try it out» vacío. Sin ejemplos, los formularios interactivos arrancan en blanco y el desarrollador tiene que inventarse cada valor para probar.
  • Mocks pobres. Los servidores de simulación que se apoyan en el contrato devuelven placeholders genéricos en lugar de datos creíbles, lo que degrada las pruebas de integración tempranas.
  • Onboarding más lento. Un ejemplo vale más que mil descripciones: acelera la comprensión de la API a quien la consume por primera vez.

La alternativa manual no escala. Un contrato mediano tiene decenas de esquemas y cientos de propiedades; mantener sus ejemplos al día, coherentes con los tipos y formatos, es un trabajo repetitivo que casi nunca se hace y que envejece mal.

Qué es openapi-examples-generator

openapi-examples-generator es una CLI que recorre tu documento OpenAPI/Swagger y, allí donde hay un esquema pero no hay example ni examples, genera un valor de ejemplo coherente con ese esquema y lo inserta en el sitio correcto del contrato. Por debajo utiliza openapi-sampler (de Redocly) como motor de generación, el mismo que emplean herramientas del ecosistema para producir muestras a partir de schemas.

Del esquema al ejemplo: openapi-examples-generator rellena el campo example a partir del esquema
De un esquema «mudo» a un contrato con ejemplos realistas, generados automáticamente.

Sus características de partida son las que uno espera de una herramienta pensada para encajar en un flujo contract-first real:

  • Compatible con Swagger 2.0, OpenAPI 3.0 y OpenAPI 3.1.
  • Acepta y produce tanto YAML como JSON.
  • Funciona en el sitio (sobrescribe el archivo, al estilo eslint --fix) o hacia otro fichero, a stdout, o en modo comprobación.
  • Nunca pisa los ejemplos escritos a mano, salvo que se lo pidas explícitamente.
  • Inserta siempre en campos oficiales del estándar, evitando el clásico problema de los siblings de $ref.

Instalación

El proyecto es un paquete Node. Lo primero es instalar dependencias:

npm install

Con eso ya puedes ejecutarlo como script: node bin/cli.js <input>. Si prefieres tener el comando openapi-examples disponible directamente en tu terminal, tienes tres opciones:

  • npm link (recomendado para desarrollo local): registra el paquete globalmente mediante un symlink, de modo que cualquier cambio en el código se refleja al instante. Ideal si vas a trastear con la propia herramienta.
  • npm install -g .: copia el paquete en la instalación global de Node. Útil si vas a mover o borrar la carpeta del repositorio después, o distribuir un .tgz con npm pack.
  • npx: npx . <input> [opciones] ejecuta la CLI directamente desde el repo sin tocar el PATH global. Perfecto para pruebas rápidas o en CI.
# opción recomendada en desarrollo
npm link
openapi-examples --version

Uso básico

La invocación mínima es openapi-examples <input> [opciones]. Sin ninguna bandera de salida, sobrescribe el archivo de entrada en el sitio, igual que un formateador:

# genera ejemplos y sobrescribe el archivo original
openapi-examples swagger.yaml

# escribe en otro archivo y deja intacto el original
openapi-examples swagger.yaml -o swagger.examples.yaml

# vuelca el resultado a stdout
openapi-examples swagger.yaml --stdout

# fuerza el formato de salida (por defecto, el mismo que la entrada)
openapi-examples swagger.yaml --format json -o swagger.json

Dos banderas merecen atención especial por lo que habilitan:

  • --force: regenera y sobrescribe los ejemplos existentes, incluidos los escritos a mano. Por defecto la herramienta los respeta; esta bandera es la vía de escape cuando quieres regenerarlo todo desde cero.
  • --check: modo dry-run. No escribe nada; sale con código 0 si todo tiene ejemplo y con código 1 —más la lista de ubicaciones que faltan— si algo está sin ejemplo. Es la pieza clave para integrarlo en CI, como veremos.
  • --verbose: registra cada ubicación visitada, omitida o con advertencia. Muy útil para entender qué ha hecho la herramienta y por qué.

Control fino: qué generar y qué no

Por defecto, openapi-examples-generator cubre las cinco familias de ubicaciones donde tiene sentido un ejemplo. Cada una se puede desactivar de forma independiente si solo te interesa una parte del contrato:

--no-schema-examples   # propiedades de components.schemas/definitions y esquemas inline
--no-parameters        # parámetros query/path/header/cookie/formData
--no-request-body      # cuerpos de petición
--no-responses         # cuerpos de respuesta
--no-headers           # cabeceras de respuesta (y de encoding multipart)

Esta granularidad permite, por ejemplo, poblar únicamente las respuestas para un portal de documentación, o solo los parámetros para mejorar el «Try it out», sin tocar el resto del documento.

La parte inteligente: dónde se inyectan los ejemplos

Aquí es donde la herramienta demuestra que entiende el estándar. La regla de oro es doble: siempre escribe en un campo oficial de la especificación y nunca lo hace como hermano de un $ref «pelado». Este segundo punto es importante: muchas herramientas ignoran las propiedades que acompañan a un $ref, así que poner un ejemplo junto a él sería tirar el trabajo. openapi-examples-generator lo evita por diseño.

Dónde inyecta los ejemplos openapi-examples-generator en Swagger 2.0 y OpenAPI 3.x
Cada tipo de ubicación recibe el ejemplo en el campo oficial que corresponde a cada versión del estándar.

El comportamiento se adapta además a cada versión del estándar, que no coloca los ejemplos en los mismos sitios:

  • Parámetros. En Swagger 2.0 usa x-example (una extensión de proveedor que Swagger UI sí lee, porque el Parameter Object 2.0 no tiene campo oficial). En OpenAPI 3.x usa example, incluidos los parámetros con content (el valor va en param.content[mediaType].example).
  • Cuerpos de petición y respuesta. En Swagger 2.0, response.examples[mime] (campo oficial, hermano de schema); en OpenAPI 3.x, content[mediaType].example.
  • Cabeceras. x-example en Swagger 2.0 y example en OpenAPI 3.x, cubriendo también las cabeceras de encoding en multipart.
  • Propiedades de esquema. El campo oficial example del Schema Object se rellena en cada propiedad escalar «hoja» que no lo tenga ya, recorriendo de forma recursiva objetos anidados, elementos de arrays y ramas de allOf, tanto en esquemas reutilizables como anónimos.

Un par de decisiones de diseño que evitan sorpresas: la herramienta nunca sobrescribe una propiedad con ejemplo escrito a mano ni un nodo que sea un $ref pelado (ese caso ya lo cubre el esquema referenciado). Y el nodo raíz de un esquema reutilizable (un Order, un Pet…) no recibe un ejemplo global estampado, ni tampoco los parámetros formData de tipo fichero. Además, el pase de propiedades se ejecuta antes que el de parámetros, peticiones y respuestas, de modo que el ejemplo compuesto de un cuerpo sale coherente con las propiedades ya rellenadas.

La forma plural: –examples-list

OpenAPI 3.x admite, además del singular example, una forma plural y reutilizable. La bandera --examples-list la activa:

  • En parámetros, cabeceras y media types (OpenAPI 3.x), en lugar de example crea una entrada reutilizable en components.examples.<nombre> y la referencia desde el punto de uso con examples: { generated: { $ref: ... } }. El nombre se deriva del operationId más el campo (por ejemplo getPetById_Param_petId) y es determinista: volver a ejecutar actualiza la misma entrada en lugar de acumular duplicados.
  • En propiedades de esquema de documentos OpenAPI 3.1, usa la forma examples: [ ... ] (la de array de JSON Schema 2020-12). En OpenAPI 3.0 y Swagger 2.0, las propiedades siguen usando example en singular con esta bandera activada, porque esa forma plural no es válida ahí.
  • En Swagger 2.0, --examples-list no afecta a parámetros ni cabeceras (2.0 no tiene mecanismo plural/reutilizable para ellos); en cambio response.examples ya es de por sí un mapa por tipo MIME. La herramienta lo registra con --verbose en lugar de fallar.

Con --force, cambiar de modo (singular ↔ plural) en la misma ubicación limpia la clave del modo anterior: example y examples nunca coexisten en el mismo sitio. Eso sí, las entradas que queden sin referenciar en components.examples tras volver al modo singular no se borran automáticamente —quedan huérfanas (el documento sigue siendo válido, pero linters como @redocly/cli lo marcarán). Es una limitación conocida, no crítica.

Integración en CI/CD: el contrato como puerta de calidad

El modo --check convierte la herramienta en una puerta de calidad para tus pull requests. No escribe nada y no necesita permisos de escritura: simplemente falla si el contrato tiene esquemas sin ejemplo, señalando dónde.

# en tu pipeline: falla el PR si faltan ejemplos
openapi-examples swagger.yaml --check

El flujo es sencillo: si el check falla porque alguien añadió un endpoint nuevo o borró un ejemplo a mano, ejecutas la herramienta sin --check, revisas el diff y lo confirmas en el commit. Así garantizas que ningún contrato llega a producción «mudo», sin cargar al desarrollador con la escritura manual de cada valor. Encaja de forma natural con el resto de controles contract-first: validación de esquema, linting con Spectral o Redocly, y comprobación de breaking changes.

Limitaciones conocidas

La honestidad sobre los límites forma parte de una buena herramienta. Estas son las que conviene tener presentes:

  • No resuelve $ref externos (./otro-archivo.yaml#/X) —openapi-sampler tampoco los soporta—. La CLI avisa y omite esos nodos en lugar de fallar.
  • Todavía no soporta $ref a parámetros, respuestas, requestBody o path items compartidos (poco frecuentes en la práctica). Los detecta y los omite con una advertencia en --verbose, sin romper el resto de la ejecución.
  • Las cabeceras con content (content-keyed headers, poco habituales) quedan fuera de alcance por ahora.
  • Las entradas huérfanas en components.examples tras un cambio de modo con --force no se limpian solas.
  • Al reserializar YAML se preserva formato, orden y comentarios de todo lo que no se toca, salvo el ajuste de línea de descripciones largas (efecto secundario de desactivar el wrapping para que los valores generados no se corten a la mitad).

Por qué encaja en una estrategia contract-first

En APIAddicts defendemos que el contrato es la fuente de la verdad de una API, y que todo lo que rodea a ese contrato —documentación, mocks, pruebas, portales— debe derivarse de él de forma automática y consistente. Los ejemplos son una pieza de esa cadena que casi siempre se descuida. Automatizar su generación tiene tres efectos inmediatos: la documentación mejora sin esfuerzo humano, los mocks se vuelven creíbles y el contrato deja de degradarse con cada cambio, porque regenerar es cuestión de un comando.

Al insertar únicamente en campos oficiales y respetar el trabajo manual, openapi-examples-generator se comporta como un buen ciudadano del ecosistema: puedes adoptarlo en un contrato existente sin miedo a romper nada y quitártelo igual de fácil. Es exactamente el tipo de utilidad pequeña, enfocada y componible que hace más llevadero el governance de APIs a escala.

Cómo empezar

openapi-examples-generator es software libre de la APIAddicts Foundation y está disponible en GitHub. Clónalo, pruébalo contra uno de tus contratos con --stdout para ver el resultado sin tocar nada, y si te convence, intégralo en tu pipeline con --check. Las contribuciones —issues, mejoras, casos límite— son bienvenidas.

👉 Repositorio: github.com/apiaddicts/openapi-examples-cli

¿Ya usas ejemplos generados automáticamente en tus contratos OpenAPI? Cuéntanos tu experiencia y qué otras piezas del ciclo de vida te gustaría automatizar. En la APIAddicts Foundation seguimos construyendo herramientas abiertas para una gestión de APIs más sencilla y consistente.

Publicaciones Similares