Todo proyecto necesita configuración, y tienes tres opciones principales: JSON, YAML o TOML. He usado las tres extensamente, y cada una me vuelve loco de maneras diferentes. Aquí va mi opinión honesta sobre cuándo usar cuál.
JSON: El soldado universal
Ya conoces JSON. Está en todas partes. Cada lenguaje puede parsearlo. Pero seamos honestos sobre sus debilidades como archivo de configuración:
- Sin comentarios. Literalmente no puedes explicar qué hace una configuración. Eso es absurdo para un archivo de config.
- Sin comas al final. Añades una línea nueva al final, olvidas la coma en la línea anterior — y tu config se rompe.
- Comillas por todas partes. Cada clave necesita comillas dobles:
{"port": 8080}en vez de simplementeport: 8080.
A pesar de todo esto, JSON lo usan para configuración npm (package.json), TypeScript (tsconfig.json), VS Code (settings.json) y más. ¿La razón? Cero ambigüedad. JSON es tan estricto que solo hay una forma de interpretarlo.
YAML: Bonito pero peligroso
YAML se ve increíble. Limpio, minimalista, legible para humanos. Pero tiene algunas trampas notorias:
Ese es el "problema de Noruega" que mencioné en el artículo de YAML. YAML 1.1 trata NO, YES, ON, OFF como booleanos. Se ha corregido en YAML 1.2, pero muchos parsers todavía usan el comportamiento de 1.1 por defecto.
Luego está la sensibilidad a la indentación. Un solo espacio mal puesto puede cambiar completamente el significado de tu archivo — y el mensaje de error será terrible.
Dicho esto, YAML es el estándar para Docker Compose, Kubernetes, GitHub Actions y Ansible. Si estás en el espacio DevOps/cloud, la fluidez en YAML es obligatoria.
TOML: El especialista en configuración
TOML (Tom's Obvious Minimal Language) fue diseñado específicamente para configuración. Su objetivo es ser obvio — lo que significa que (casi) no hay forma de malinterpretar un archivo TOML.
Así se ve una configuración TOML:
Lo que TOML hace realmente bien: tipos nativos de fecha/hora (created = 2026-03-08T10:30:00Z), sin problemas de indentación, comentarios con # y una sintaxis que es genuinamente difícil de arruinar.
¿La desventaja? Las estructuras profundamente anidadas se vuelven verbosas. TOML es genial para configs planas, pero si necesitas cinco niveles de anidación, YAML o JSON podrían ser más legibles.
TOML lo usan Rust (Cargo.toml), Python (pyproject.toml), Hugo y un número creciente de herramientas.
Mis recomendaciones
| Escenario | Elige | Por qué |
| Config generada por máquina | JSON | Más estricto y compatible |
| DevOps/infraestructura | YAML | El ecosistema lo espera |
| Configuración de app | TOML | Comentarios + mínima ambigüedad |
| Configuraciones simples clave-valor | TOML | Lo más limpio para configs planas |
| Estructuras anidadas complejas | YAML | Mejor sintaxis anidada |
Conclusión
La misma config en los tres formatos
Ver los mismos datos en los tres formatos realmente destaca las diferencias. Aquí tienes una configuración de app simple:
JSON:
YAML:
TOML:
Observa cómo JSON requiere todas esas comillas y llaves, YAML es el más conciso pero depende de la indentación, y TOML encuentra un punto medio con encabezados de sección explícitos y sin dependencia de la indentación.
Errores comunes en archivos de configuración
YAML: Conversión de tipos accidental. Más allá del problema de Noruega, YAML también interpretará 3.10 como el número 3.1 (eliminando el cero final), y 1_000 como 1000. Si tus valores de config son cadenas de versión como 3.10, siempre ponlas entre comillas: version: "3.10".
JSON: Olvidar que el orden no importa. Los objetos JSON son desordenados por especificación. Si tu procesamiento de config depende del orden de las claves, estás construyendo sobre una base frágil. Algunos parsers preservan el orden de inserción, otros no.
TOML: Confusión con arrays de tablas. TOML usa [[dobles.corchetes]] para arrays de tablas, lo que confunde a los principiantes. Así defines múltiples servidores:
Configs específicas por entorno
Un área donde los tres formatos tienen dificultades es el manejo de sobrescrituras específicas por entorno (dev vs staging vs producción). Las soluciones comunes incluyen:
- Múltiples archivos:
config.base.yaml+config.production.yamlcon fusión profunda - Interpolación de variables de entorno: Algunas herramientas YAML soportan la sintaxis
${DB_HOST}, pero no es estándar - Herramientas externas: Doppler, HashiCorp Vault o servicios de configuración cloud-native
Personalmente, me inclino por un enfoque simple: un archivo de config con valores predeterminados sensatos, y variables de entorno para cualquier cosa que cambie entre entornos. Los tres formatos pueden leer variables de entorno a nivel de aplicación, así que el formato de config en sí no necesita soportar interpolación.
Popularidad del formato por ecosistema
| Ecosistema | Formato principal | Ejemplos notables |
| JavaScript/Node.js | JSON | package.json, tsconfig.json, .eslintrc.json |
| Python | TOML | pyproject.toml, Cargo.toml (Rust) |
| DevOps/Cloud | YAML | docker-compose.yml, manifiestos k8s, GitHub Actions |
| Go | TOML/YAML | Ambos ampliamente usados, sin estándar único |
| .NET | JSON | appsettings.json (reemplazó web.config basado en XML) |
Conclusión
No hay una única respuesta correcta. Usa JSON cuando necesites máxima compatibilidad. Usa YAML cuando el ecosistema lo exija (Kubernetes no va a empezar a aceptar TOML). Usa TOML cuando quieras comentarios y mínimas sorpresas.
JSONC y JSON5: JSON con rueditas de entrenamiento
Bueno, hemos estado criticando a JSON por no soportar comentarios y comas al final. Pero aquí está lo que nadie te dice: en realidad hay variantes de JSON que arreglan estas molestias, y probablemente has estado usando una de ellas sin darte cuenta.
Primero: JSONC (JSON with Comments). Si alguna vez abriste un tsconfig.json y pensaste "espera, hay comentarios aquí... ¿no se supone que JSON no permite comentarios?" — sí, eso es JSONC. Es básicamente JSON pero puedes usar comentarios de una línea con // y comentarios de bloque con /* */. VS Code usa JSONC para sus archivos settings.json, launch.json y keybindings.json. El tsconfig.json de TypeScript también es técnicamente JSONC, no JSON estricto.
Así se ve JSONC:
Luego está JSON5, que va más allá. JSON5 relaja varias de las reglas más estrictas de JSON:
- Cadenas con comillas simples:
{'name': 'Sarah'}— ¡por fin! - Comas al final:
{"a": 1, "b": 2,}— no más ruido en los diffs - Claves sin comillas (si son identificadores válidos):
{name: "Sarah"} - Números hexadecimales:
0xFF - Cadenas multilínea con continuación por barra invertida
Infinity,-InfinityyNaNcomo números válidos
JSON5 es genial para archivos de config donde los humanos son la audiencia principal. Algunas herramientas lo soportan nativamente — por ejemplo, el .babelrc de Babel puede ser JSON5. Pero no uses JSON5 para respuestas de API o intercambio de datos. El sentido del JSON estricto es que todos acuerdan el formato. JSON5 es para humanos, no para máquinas.
Mi regla general: si una herramienta soporta JSONC o JSON5, úsalo. Literalmente no hay desventaja en tener comentarios en tus archivos de config. Pero si estás escribiendo una librería que lee config, soporta JSON estándar primero y JSONC/JSON5 como extras opcionales.
Anclas y alias de YAML: Config DRY
Aquí viene la verdadera característica asesina de YAML que muchos desarrolladores nunca descubren: anclas y alias. Te permiten definir un bloque de config una vez y reutilizarlo en todas partes. Básicamente DRY (Don't Repeat Yourself) para archivos de config.
Un ancla se marca con &nombre y un alias la referencia con *nombre. Aquí tienes un ejemplo práctico de Docker Compose:
¿Ves lo que pasó? Definimos configuraciones comunes una vez con &common y las incorporamos en tres servicios con <<: *common. Sin anclas, estarías copiando y pegando esa política de reinicio y config de logging en cada servicio. ¿Y cuando necesites cambiar la rotación de logs? Un solo lugar en vez de doce.
También puedes usar anclas para valores más simples — no solo para maps:
Ahora, las trampas. La clave de fusión << que hace que las anclas sean realmente poderosas, en realidad no es parte de la especificación de YAML 1.2. Era una extensión de tipo de YAML 1.1, y aunque la mayoría de los parsers populares todavía la soportan, técnicamente no es estándar. Así que si usas un parser estricto de YAML 1.2, las claves de fusión podrían no funcionar.
Además, las anclas solo funcionan dentro de un solo archivo. No puedes referenciar un ancla definida en otro archivo YAML. ¿Y los mensajes de error cuando te equivocas en el nombre de un alias? Normalmente algo como "undefined alias" sin ningún contexto sobre dónde se suponía que estaba el ancla. Clásico YAML.
TOML a fondo: Características avanzadas
La mayoría conoce los básicos de TOML — secciones con [corchetes], pares clave-valor, comentarios con #. Pero TOML tiene algunas características genuinamente geniales que no reciben suficiente atención. Déjame guiarte por ellas.
Claves con puntos te permiten definir estructuras anidadas sin encabezados de sección:
Esto es práctico cuando solo tienes un par de valores anidados y no quieres crear una sección entera para ellos.
Tablas inline te dan una sintaxis compacta tipo JSON para objetos pequeños:
Usa las tablas inline con moderación — no pueden abarcar múltiples líneas y se vuelven ilegibles rápido si metes demasiado en ellas.
Cadenas multilínea vienen en dos sabores, y aquí es donde TOML se vuelve sorprendentemente considerado:
La cadena básica con triple comilla (""") procesa secuencias de escape, mientras que la versión literal (''') trata todo como texto crudo. Esto es perfecto para patrones regex o rutas de archivos de Windows donde no quieres que las barras invertidas se interpreten como escapes.
Tipos nativos de fecha/hora son algo que ni JSON ni YAML maneja así de limpiamente:
Estos son tipos de primera clase en TOML, no cadenas fingiendo ser fechas. Tu parser TOML te dará objetos reales de fecha/hora, no cadenas que tengas que parsear tú mismo.
¿Por qué eligió Cargo de Rust TOML? Porque las configs de Cargo son exactamente el punto ideal para TOML: moderadamente anidadas, editadas por humanos, necesitan comentarios y se benefician del tipado estricto. No quieres que tus versiones de dependencias se interpreten silenciosamente como floats (te estoy mirando, YAML).
Consideraciones de seguridad
Vale, esta es la sección donde las cosas se ponen un poco asustadizas. Si estás cargando archivos de config de fuentes no confiables — o incluso si crees que no — necesitas conocer los ataques de deserialización.
El ejemplo por excelencia es el yaml.load() de PyYAML. En versiones anteriores, esta función de apariencia inocente podía ejecutar código Python arbitrario embebido en un archivo YAML. No estoy bromeando. Mira esto:
Si alguien cuela esto en una config YAML y tu app Python lo carga con yaml.load() en vez de yaml.safe_load(), literalmente ejecutará ese comando del sistema. Borrar todo. Instalar una puerta trasera. Lo que el atacante quiera.
La solución es facilísima — siempre usa yaml.safe_load() en Python:
La documentación de PyYAML ahora advierte sobre esto, y las versiones más nuevas muestran un aviso de deprecación si usas yaml.load() sin especificar un Loader. Pero todavía hay incontables tutoriales y respuestas de Stack Overflow mostrando la versión insegura. Es una mina terrestre escondida a plena vista.
Luego está el ataque "billion laughs" (también llamado bomba XML, pero funciona con YAML también). La idea es expansión recursiva — defines entidades que referencian otras entidades, creando crecimiento exponencial:
Cada nivel multiplica los datos por 5, así que para el nivel 8 o 9 estás viendo gigabytes de datos de unas pocas líneas de YAML. La mayoría de los parsers YAML modernos tienen límites de profundidad y expansión para prevenir esto, pero vale la pena saberlo.
JSON es inherentemente más seguro porque no tiene ninguna semántica de ejecución. No hay forma de embeber código, no hay constructores de tipo, no hay expansión de entidades. Un parser JSON simplemente lee datos — cadenas, números, booleanos, arrays y objetos. Eso es todo. Esta es una de las ventajas subestimadas de la simplicidad de JSON. Cuando la seguridad importa, la falta de características de JSON es en realidad una característica.
TOML también es bastante seguro — no tiene capacidades de ejecución de código ni expansión recursiva. Pero está menos probado en batalla que los parsers JSON, así que mantén tus bibliotecas TOML actualizadas.
En resumen: si aceptas archivos de config de usuarios o fuentes externas, JSON es la opción más segura. Si debes usar YAML, siempre usa funciones de carga segura y considera ejecutar un linter YAML para detectar construcciones sospechosas.
Ejemplos reales de archivos de configuración
La teoría está genial, pero veamos archivos de config reales que encontrarás en la práctica. He anotado cada uno para resaltar patrones específicos del formato.
Workflow de GitHub Actions (YAML):
Aquí es donde YAML realmente brilla. La sintaxis de workflow de GitHub Actions sería dolorosa en JSON — todas esas listas anidadas y la estructura basada en indentación se mapea naturalmente a YAML. También puedes ver cómo los comentarios ayudan a explicar la estrategia de matrix.
Cargo.toml de Rust (TOML):
Fíjate cómo el manifiesto de Cargo usa tablas inline para dependencias con features. La sintaxis [[bin]] con dobles corchetes define un array de tablas — cada entrada [[bin]] añade otro target binario. TOML mantiene esto plano y legible sin juegos de indentación.
package.json (JSON):
El clásico. Sin comentarios, muchas comillas, pero cada herramienta del planeta puede leerlo. Lo que hace que package.json funcione a pesar de las limitaciones de JSON es que el esquema es tan conocido — no necesitas comentarios para explicar qué hace scripts.build porque cada desarrollador JavaScript ya lo sabe.
.prettierrc (JSON):
Config simple de clave-valor plana. Honestamente, esto sería un poco más bonito como TOML (¡comentarios!) o incluso JSONC, y Prettier soporta otros formatos. Pero JSON es el predeterminado, y para algo tan simple, no importa mucho.
Migración entre formatos
Así que has decidido que el formato de config de tu proyecto fue un error y quieres cambiar. O quizás estás trayendo config de una herramienta que usa un formato diferente. De cualquier manera, necesitas convertir entre TOML, YAML y JSON. Te digo, no siempre es tan suave como esperarías.
Herramientas de conversión:
- yq — La navaja suiza para YAML. Puede convertir entre YAML, JSON, TOML y XML.
yq -o=json config.yamlte da salida JSON. Es comojqpero para YAML. - toml-cli y taplo — Procesadores TOML de línea de comandos. Taplo es particularmente bueno para formateo y validación de TOML.
- Scripts de una línea en Python — En un apuro,
python -c "import yaml, json, sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yamlconvierte YAML a JSON. No es bonito, pero funciona. - Convertidores online — Para conversiones rápidas puntuales, nuestros formateadores pueden ayudar. Pega tu config en el formateador apropiado, límpiala y reescríbela manualmente en el formato destino.
Cuándo migrar:
- ¿Tu equipo sigue cometiendo errores de indentación YAML en configs de CI? Quizás cambiar a TOML reduce esos dolores de cabeza.
- ¿Necesitas comentarios en un archivo de config JSON? Considera migrar a JSONC (si la herramienta lo soporta) o TOML.
- ¿Estás construyendo un nuevo proyecto en Rust/Python y el ecosistema espera TOML? No luches contra ello — ve con TOML.
Trampas comunes al migrar:
El parseo implícito de fechas de YAML te morderá. Si tienes un valor YAML como release: 2024-03-08, YAML lo interpreta como un objeto de fecha, no una cadena. Convierte eso a JSON y podrías obtener "release": "2024-03-08T00:00:00Z" o "release": "2024-03-08" dependiendo de tu convertidor. Siempre prueba tu salida.
El tipado estricto de TOML significa que no puedes tener arrays de tipos mixtos. En JSON y YAML, [1, "two", true] es perfectamente válido. En TOML, cada elemento de un array debe ser del mismo tipo. Si tus datos fuente tienen arrays mixtos, necesitarás reestructurar.
Y aquí está el grande: los comentarios se pierden. JSON no soporta comentarios, así que si conviertes de TOML o YAML a JSON, todos tus comentarios cuidadosamente escritos desaparecen. Yendo en la dirección opuesta (JSON a YAML/TOML), querrás añadir manualmente comentarios para explicar configuraciones no obvias, porque la versión JSON ciertamente no los tenía.
Una cosa más — las anclas y alias de YAML no tienen equivalentes en JSON o TOML. Si tu config YAML depende de anclas para config DRY, convertir a otro formato significa que tendrás que duplicar manualmente esos bloques compartidos. Eso puede ser una expansión significativa en el tamaño del archivo para configs complejas.
Pruébalo tú mismo
Sea cual sea el formato que elijas, mantener tus configs bien formateadas las hace más fáciles de revisar y depurar. Nuestro TOML Formatter limpia archivos TOML desordenados al instante. El YAML Formatter corrige problemas de indentación antes de que causen problemas. Y el JSON Formatter hace legibles de un vistazo incluso las configs JSON profundamente anidadas.