La tediosa tarea de las definiciones de esquema anidadas

La especificación OpenAPI (OAS) es la forma estándar e independiente del lenguaje de describir la interfaz de una API RESTful (anteriormente conocida como “Swagger”). Sustenta la documentación autogenerada, la generación de SDK de cliente y los servidores mock.

Escribir a mano el “Esquema” de un cuerpo de solicitud o respuesta — mapeando objetos profundamente anidados a type / properties / required / items — es lento y propenso a errores.

El Generador de JSON a OpenAPI toma un payload JSON de muestra y produce automáticamente una definición components/schemas.

Genere un esquema de OpenAPI a partir de JSON | Compatible con Swagger

Cómo funciona la inferencia de tipos

El generador recorre el JSON valor por valor, mapeando cada uno a un tipo de OpenAPI.

private static inferSchema(value: unknown): OpenApiSchema {
    if (value === null) return { type: 'null' };

    if (Array.isArray(value)) {
        // si todos los elementos comparten un esquema, se usa directamente; si no, se envuelve en oneOf
        const itemSchemas = this.mergeSchemas(value.map((item) => this.inferSchema(item)));
        const items = itemSchemas.length === 1 ? itemSchemas[0] : { oneOf: itemSchemas };
        return { type: 'array', items };
    }

    if (typeof value === 'number') {
        return { type: Number.isInteger(value) ? 'integer' : 'number' };  // distingue entero de decimal
    }
    // los objetos recurren a properties; cada clave presente se trata como obligatoria
}

Dos detalles importan aquí:

  1. Los números se clasifican con Number.isInteger30 se convierte en integer, 30.5 en number.
  2. Los tipos mixtos dentro de un array se convierten en oneOf. Un array como ["admin", 1, true] produce items: { oneOf: [{type: string}, {type: integer}, {type: boolean}] }.

Detección automática de cadenas de fecha

Las cadenas ISO 8601 se comparan con una expresión regular y reciben automáticamente format: date-time.

if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(stringValue)) {
    return { type: 'string', format: 'date-time' };
}

Un valor como 2026-01-15T12:00:00Z se detecta, pero las cadenas de solo fecha (2026-01-15) o las que tienen un desfase de zona horaria (+09:00) no coinciden con este patrón — necesitará añadir format: date manualmente para esos casos después de generar.

Uso y ejemplo de salida

{
  "id": 123,
  "name": "Yamada Taro",
  "email": "taro@example.com",
  "roles": ["admin", "editor"],
  "profile": {
    "createdAt": "2026-01-15T12:00:00Z",
    "isActive": true
  }
}

A partir de esto, id se infiere como integer, name/email como string, roles como array, profile como un object anidado, y createdAt como un string con format: date-time.

  1. Obtenga un payload JSON real de una llamada a la API
  2. Péguelo en el Generador de JSON a OpenAPI
  3. Obtenga una definición components/schemas en segundos
  4. Fusione la definición generada en su openapi.yaml

Cada clave presente se convierte en “obligatoria” — por diseño

Bajo la implementación actual, cada clave presente en el JSON de muestra se marca como required.

for (const [key, val] of Object.entries(value)) {
    properties[key] = this.inferSchema(val);
    required.push(key);   // cualquier clave presente es obligatoria incondicionalmente
}

Esto es una simplificación deliberada: a partir de un único payload JSON de muestra, no hay forma de saber si una clave es genuinamente obligatoria o simplemente tenía un valor esa vez. Si su API real tiene campos opcionales, elimínelos de required manualmente después de generar.

Qué revisar después de generar

Trate un esquema OpenAPI derivado de JSON como un borrador de alta calidad, no como una especificación terminada.

  • Elimine de required los campos que legítimamente pueden omitirse
  • Confirme si los campos numéricos (IDs, importes, conteos) deberían ser integer o number
  • Confirme que las cadenas de fecha tienen el format esperado — solo date-time se detecta automáticamente
  • Compruebe que los arrays no se muestrearon vacíos (un array vacío se convierte en items: {})
  • Añada description y example para que los consumidores entiendan qué significa cada campo

Cumplimiento de OpenAPI 3.1

El esquema generado apunta a OpenAPI 3.1.0. En lugar del nullable: true de OpenAPI 3.0, usa la forma type: "null" (o de tipo unión) estandarizada en 3.1. Si su proyecto existente está estandarizado en OpenAPI 3.0, puede necesitar traducir esta diferencia.

Preguntas frecuentes

¿Funciona también para Swagger?

Sí. OpenAPI se llamaba antes Swagger, y los términos “esquema Swagger” y “Swagger UI” siguen siendo comunes. El esquema generado puede usarse directamente con Swagger UI y herramientas de documentación similares.

¿Puedo usarlo tanto para cuerpos de solicitud como de respuesta?

Sí — JSON de solicitud POST/PUT, JSON de respuesta GET, payloads de webhook, cualquier cosa con una estructura JSON identificable funciona como punto de partida.

¿Qué pasa si un array tiene tipos mixtos?

El generador lo expresa con oneOf, listando cada tipo distinto. Decida como parte del diseño de su API si unificar el tipo o aceptar el oneOf tal cual.

¿Debería preocuparme por OpenAPI 3.0 frente a 3.1?

Si su proyecto existente está estandarizado en OpenAPI 3.0, verifique cómo se maneja nullable frente a type: null antes de importar la salida. Para proyectos nuevos o herramientas internas, quedarse con la representación de OpenAPI 3.1 suele estar bien.

Resumen

  • La inferencia de tipos es un recorrido recursivo de valores: los números se dividen en entero/decimal, los arrays de tipos mixtos se convierten en oneOf
  • La detección de fechas se basa en expresiones regulares y solo cubre el formato date-time — todo lo demás necesita ajuste manual
  • Cada clave presente en la muestra se convierte en required — elimine los campos opcionales después de generar
  • La salida apunta a OpenAPI 3.1.0

La generación automática es un borrador. Añada description y example después para convertirlo en documentación que su equipo y los consumidores de la API realmente disfrutarán leer.