🧬 JSON → Definición de Tipos
Pega JSON y genera al instante definiciones de tipos en TypeScript / PHP / Python / Go / Rust. Soporta objetos y arrays anidados.
💡 Consejos
• Los objetos anidados se extraen automáticamente como tipos separados.
• Los tipos de elementos de array se infieren. Los arrays vacíos se convierten en any[] / []interface{}.
• null se trata como optional / nullable, ej. string | null.
• Cambia el nombre del tipo raíz desde el campo de arriba.
🔗 Herramientas relacionadas
📖 Dónde se suele tropezar
Pega JSON y genera definiciones de tipo para TypeScript, PHP, Python, Go, Rust, Kotlin y Swift, extrayendo los objetos anidados como tipos aparte e infiriendo el tipo de los elementos de los arrays. Todo se ejecuta en el navegador. Sólo puede inferirse la forma presente en la muestra que le has dado: una única respuesta de API es lo que volvió aquella vez, no la especificación. Toma la salida como punto de partida para editar a mano, no como un producto acabado.
| Caso | Qué ocurre | Qué hacer |
|---|---|---|
| Un tipo hecho con una muestra no aguanta en producción | La inferencia trabaja sobre la premisa de que lo que ha visto es todo lo que hay. Por tanto, un campo ausente de la muestra no existe en el tipo, y un campo que casualmente traía valor se trata como obligatorio. Las API reales devuelven formas distintas cuando una búsqueda no encuentra nada, cuando hay un error, cuando faltan permisos y para registros antiguos. Los campos tipo enumeración son el caso más agudo: si la muestra sólo mostró "active", el tipo pasa a ser el literal "active" y en cuanto llega "archived" el tipo miente. |
Pásale varias respuestas. Toma al menos cuatro casos —uno normal, uno vacío, un error y un valor límite— y compara los tipos resultantes: así se ve qué campos son de verdad obligatorios. Si existe una especificación OpenAPI, genera a partir de ella: openapi-typescript y oapi-codegen parten de una descripción de todas las formas que pueden devolverse, un nivel de fiabilidad distinto al de inferir sobre muestras. Y lee siempre lo generado: un tipo en el que todos los campos son obligatorios y una enumeración es un solo literal es la señal de que le diste una única muestra. |
| Los arrays vacíos y los nulos no determinan nada | De "tags": [] no hay forma de conocer el tipo del elemento; el resultado es un tipo que lo admite todo, como any[], []interface{} o List<Any>, y la ventaja de la comprobación de tipos desaparece por completo. null es igual de poco informativo: si "deleted_at": null es siempre nulo o nulo sólo esta vez no se deduce de una muestra. Más de fondo: JSON distingue una clave ausente de una clave con valor nulo, y muchos sistemas de tipos difuminan esa distinción; en TypeScript, ?: y | null no son lo mismo. |
Cuando una respuesta traiga un array vacío, pásale también otra que sí tenga elementos: con uno solo basta para fijar el tipo. Si no puedes conseguirla, escribe ese tipo de array a mano: piensa en la salida como automatizar nueve décimas partes y rellenar el resto, y el trabajo deja de pesar. Para null, sólo la documentación de la API te lo dirá: si distingue clave ausente de clave nula, lo preciso en TypeScript es escribir ambas cosas, como en deleted_at?: string | null. Ante la duda, tira a lo laxo: un tipo laxo comprobado en ejecución es más seguro que uno estricto que revienta en ejecución. |
| El tipo numérico significa cosas distintas según el lenguaje | JSON tiene exactamente un tipo numérico: sin distinción entre entero y decimal, sin precisión. El generador ha de elegir algo por lenguaje: float64 en Go, i64 o f64 en Rust, number en TypeScript. El caso peligroso son los identificadores: recibe un entero grande como float64 o number y, pasado dos elevado a cincuenta y tres, la precisión desaparece y el valor se reescribe en silencio. Que 9007199254740993 pase a 9007199254740992 no lanza ningún error. Las cadenas con forma de fecha, naturalmente, siguen siendo string. |
Corrige siempre a mano, tras generar, los tipos de identificadores, importes y marcas de tiempo. Tratar un identificador como cadena es lo más seguro: no hay motivo para guardar como número un valor con el que nunca haces aritmética, y de hecho las API de Twitter y Discord devuelven los identificadores grandes como cadenas. Nunca guardes dinero en coma flotante: por la misma razón por la que 0.1 + 0.2 no es 0.3, usa un entero en la unidad mínima o el tipo decimal de tu lenguaje. Pasar las marcas de tiempo de string a un tipo de fecha real hace que el sistema de tipos te obligue a tratar la zona horaria. Lee el tipo generado línea a línea y pregúntate si haces aritmética con ese valor: si no, una cadena vale. |
No tomes un tipo generado por una frontera de confianza. Los tipos de TypeScript, en particular, sólo existen en tiempo de compilación y no verifican nada en ejecución: escribe await res.json() as User y el compilador creerá que es un User venga lo que venga. No es un defecto del sistema de tipos sino un diseño en el que validar en la frontera es tarea de otra capa. Para datos que llegan de fuera —respuestas de API, entradas de formulario—, añade siempre validación en ejecución con zod o valibot; el tipo puede derivarse del esquema, así que nada se mantiene por duplicado. json.Unmarshal de Go y serde de Rust sí validan y son más seguros, pero por defecto descartan en silencio los campos desconocidos: DisallowUnknownFields en Go y #[serde(deny_unknown_fields)] en Rust te permiten enterarte cuando la API cambia.
📖 Cómo usar
-
1
Ingresar o pegar JSONPega JSON en el campo izquierdo. Usa el botón Ejemplo para cargar datos de muestra rápidamente.
-
2
Seleccionar lenguaje destinoElige el lenguaje y opcionalmente cambia el nombre del tipo raíz.
-
3
Copiar y usar la definición de tiposLa definición de tipo aparece a la derecha. Cópiala y pégala en tu código.
❓ Preguntas frecuentes
¿Cómo se manejan los objetos anidados?
¿Cómo se tipan los campos null?
¿Maneja arrays JSON en el nivel raíz?
🐛 ¿Encontró un problema con esta herramienta?
Gratis, sin registro. Incluso solo los pasos para reproducir ayudan. Los informes van directamente al operador y se usan para corregir.
¡Gracias por tu reporte!
Tu reporte llegó al operador y se usará para mejorar.