YAML vs JSON vs TOML — ¿Qué formato de configuración deberías usar realmente?
YAML, JSON y TOML almacenan configuraciones. No son intercambiables. YAML convertirá silenciosamente tu código de país en un valor booleano. JSON no te permitirá dejar un comentario. TOML es el formato que nadie en tu equipo ha usado antes. Aquí te explico cómo elegir el adecuado.
En 2015, un playbook de Ansible se rompió debido a esta línea:
country: NO
La configuración se cargó sin errores. No hubo quejas del analizador. Pero country no estaba establecida como el string "NO". Estaba establecida como false. Porque en YAML 1.1, NO es un valor booleano. Así es yes, on, off, yy n. Este es el problema de Noruega, y ha estado corrompiendo silenciosamente las configuraciones durante años.
Esto no es un informe de error de YAML. Es un marco para la decisión que estás a punto de tomar: YAML, JSON o TOML para tu siguiente archivo de configuración? Cada uno tiene verdaderas implicaciones, y la respuesta «usa simplemente lo que usa el ecosistema» no siempre se aplica.
La Misma Configuración, Tres Maneras
Antes del colapso, aquí está la misma configuración de la aplicación escrita en los tres formatos:
YAML
# App configuration
app:
name: my-api
port: 8080
debug: false
database:
host: localhost
port: 5432
name: mydb
pool_size: 10
logging:
level: info
format: json
outputs:
- stdout
- /var/log/app.log
JSON
{
"app": {
"name": "my-api",
"port": 8080,
"debug": false
},
"database": {
"host": "localhost",
"port": 5432,
"name": "mydb",
"pool_size": 10
},
"logging": {
"level": "info",
"format": "json",
"outputs": [
"stdout",
"/var/log/app.log"
]
}
}
TOML
# App configuration
[app]
name = "my-api"
port = 8080
debug = false
[database]
host = "localhost"
port = 5432
name = "mydb"
pool_size = 10
[logging]
level = "info"
format = "json"
outputs = ["stdout", "/var/log/app.log"]
YAML es el más compacto pero también el más cargado sintácticamente. JSON es el más verbose pero también el más explícito. TOML se sitúa en el medio: legible sin las conversiones implícitas de YAML.
YAML: Potente, Permisivo y Lleno de Trampas
YAML es la opción predeterminada para pipelines de CI/CD (GitHub Actions, GitLab CI, CircleCI), manifestos de Kubernetes, playbooks de Ansible y la mayoría de las herramientas de desarrollo. No eliges realmente YAML — es YAML quien te elige.
Las trampas documentadas:
1. El Problema de los Booleanos (El Problema de Noruega)
YAML 1.1 — la especificación que la mayoría de los analizadores realmente implementan — trata un número alarmante de cadenas como valores booleanos:
# YAML 1.1 boolean values (all parsed as true or false)
enabled: yes # true
disabled: no # false
active: on # true
paused: off # false
valid: true # true
invalid: false # false
# The Norway Problem in practice:
country_codes:
NO: Norway # Key "NO" is fine, but value "NO" becomes false
SE: Sweden
YES: Yemen # "YES" also becomes true
# The fix: quote your strings
country_codes:
NO: "Norway"
SE: "Sweden"
YAML 1.2 (lanzada en 2009) solucionó esto — solo true y false son valores booleanos. El problema es que PyYAML no adoptó completamente el comportamiento de 1.2 hasta la versión 6.0 en 2021, y Go’s popular gopkg.in/yaml.v2 todavía utiliza semánticas de 1.1 hasta 2024. Si estás usando Psych de Ruby < 4.0 o cualquier versión anterior a 6.0 de PyYAML, estás en 1.1.
2. Los espacios de tabulación matarán tu configuración
YAML prohíbe el uso de caracteres de tabulación para la indentación. Solo los espacios son válidos. Tu editor podría mostrar tabulaciones y espacios de forma idéntica, el archivo podría parecer correcto, y YAML aún lanzará:
yaml.scanner.ScannerError: while scanning a block mapping
found character '\t' that cannot start any token
Este es el error que hace que los desarrolladores junior cuestionen sus elecciones profesionales. Configura tu editor para que expanda las tabulaciones en espacios en archivos de YAML. Cada editor lo soporta; no todos lo tienen activado por defecto.
3. Las cadenas multilineales no son evidentes
# | (literal block): preserves newlines exactly
description: |
Line one.
Line two.
Line three.
# Result: "Line one.\nLine two.\nLine three.\n"
# > (folded block): folds newlines into spaces
short_desc: >
This will all become
one long line.
# Result: "This will all become one long line.\n"
# Trailing newlines: | adds one, |+ adds all, |- strips them all
desc_stripped: |-
No trailing newline.
Nadie las recuerda sin consultarlas. El acróstico que uso: | parece un salto de línea, > parece algo que está siendo comprimido. Aún es confuso después de tres años.
Cuando YAML gana
- Estás escribiendo manifestos de Kubernetes, workflows de GitHub Actions o playbooks de Ansible — no tienes elección.
- Tu configuración tiene muchos comentarios que explican valores no obvios. YAML soporta comentarios inline; JSON y TOML también los soportan, pero YAML se siente más natural para configuraciones con muchos anotaciones.
- Tus datos tienen estructuras profundamente anidadas que se verían horribles con las tablas planas de TOML.
- El equipo ya es experto y tiene un linter (yamllint) en el pipeline.
JSON: La herramienta aburrida y confiable
JSON fue diseñado como un formato de intercambio de datos, no como un formato de configuración. Douglas Crockford decidió intencionalmente excluir los comentarios — su argumento era que los comentarios serían usados para directivas que los analizadores podrían diferenciar. Por eso package.json no tiene comentarios y tsconfig.json es técnicamente JSON con comentarios (JSONC), que es una cosa separada que la mayoría de los analizadores de JSON no soportan.
Los verdaderos problemas de JSON para archivos de configuración:
- No tiene comentarios. No puedes explicar por qué
"maxRetries": 3y no 5. No puedes dejar una nota de TODO. No puedes marcar un campo como obsoleto. Esto es realmente doloroso para archivos de configuración que sobreviven a sus autores. - No tiene comas al final. Agregar un elemento a un array significa modificar la línea anterior para añadir una coma. Cada diferencia de JSON se convierte en un cambio de dos líneas. Cada conflicto de fusión es ligeramente peor de lo que debería ser.
- Es verbose para datos anidados. Seis líneas de llaves y corchetes para lo que YAML hace en tres líneas de indentación.
- Todos los números son del mismo tipo. JSON no distingue entre enteros y flotantes.
1y1.0ambos son simplemente números, y lo que tu lenguaje los deserializa depende del analizador.
Pero la prediccibilidad de JSON también es su principal característica. Cada lenguaje tiene un analizador de JSON. La especificación es inambigua. No hay conversiones implícitas de tipos. Una cadena siempre es una cadena — "yes" nunca se convierte silenciosamente en true. Si necesitas validar una configuración de JSON de forma programática, IO Tools’ JSON Formatter puede detectar errores de sintaxis antes de que lleguen a producción — útil cuando alguien edita una configuración manualmente y olvida una coma al final.
Cuando JSON gana
- Configuraciones de API consumidas por múltiples servicios en diferentes lenguajes o entornos. JSON es universal; el soporte de TOML es escasamente disponible en algunos ecosistemas.
- Necesitas garantías estrictas de tipo. La validación de esquemas de JSON es madura, bien soportada y ampliamente utilizada (VS Code la usa para la autocompletación de configuraciones).
- La configuración es generada por máquinas. Nadie escribe JSON a mano si puede evitarlo — pero las máquinas generan JSON sin problemas.
- Estás trabajando en Node.js o JavaScript de interfaz, donde JSON es un ciudadano nativo.
TOML: Configuración opinada, hecha bien
TOML (Tom’s Obvious, Minimal Language) fue creado por Tom Preston-Werner, cofundador de GitHub, específicamente para archivos de configuración. Llegó a la versión 1.0 en enero de 2021. Es el formato predeterminado para Rust’s Cargo.toml, Python’s pyproject.toml, y sitios estáticos Hugo.
La filosofía de diseño de TOML: los tipos deben ser explícitos, la estructura debe ser plana cuando sea posible, y debe haber exactamente una forma obvia de escribir cualquier valor de configuración.
# Types are unambiguous in TOML
name = "my-app" # string: always quoted
port = 8080 # integer
threshold = 3.14 # float
enabled = true # boolean: only true/false, no yes/no
created = 2024-01-15 # date: native type
tags = ["api", "prod"] # array
# "yes" is just a string. Always.
country = "NO" # string "NO", no boolean nonsense
Las irregularidades:
- La sintaxis de arrays de tablas es realmente incómoda.
[[products]]y[products.details]se parecen pero se comportan completamente diferente. La especificación tiene sentido; la distinción visual no. - El anidamiento profundo se vuelve verbose. Lo que YAML hace en 5 líneas indentadas, TOML lo hace en 3 encabezados separados. Para configuraciones más de 3 niveles de profundidad, TOML empieza a sentirse como la herramienta equivocada.
- Disponibilidad de analizadores. Existen analizadores de TOML para cada lenguaje principal, pero varían en cumplimiento de la especificación. El conjunto de pruebas de conformidad de TOML revela constantemente casos extremos. Los analizadores de JSON han sido probados en millones de usos.
- Familiaridad del equipo. Si usas TOML fuera del ecosistema de Rust o Python, espera que al menos un miembro del equipo abra un PR con «¿qué es este formato?»
Cuando TOML gana
- Proyectos en Rust —
Cargo.tomles el estándar y la herramientería es excelente. - Proyectos en Python que usan
pyproject.toml(PEP 518) — esta es ahora la ubicación recomendada para la configuración de herramientas como Black, Ruff, mypy y pytest. - Configuraciones simples y planas donde la sensibilidad a la indentación de YAML sería un problema.
- Quieres soporte nativo de fechas y horas sin serializar a cadenas.
La guía rápida de decisión
- Kubernetes / pipeline de CI/CD / playbook de Ansible? YAML. No hay elección.
- Configuración de API consumida por múltiples servicios en diferentes lenguajes? JSON.
- Proyecto en Rust? TOML (convención de Cargo.toml).
- Configuración de proyecto en Python (linters, formatters, herramientas de compilación)? TOML (pyproject.toml es ahora el estándar).
- Configuración de sitio estático (Hugo, Zola)? TOML, aunque estos normalmente soportan los tres.
- Configuración de proyecto en Node.js? JSON (ecosistema de package.json), o YAML si necesitas comentarios.
- Los humanos editarán esta configuración frecuentemente y necesitan dejar notas? YAML o TOML (ambos soportan comentarios). No JSON.
- Quieres garantías estrictas de tipo y validación de esquema? JSON + esquema de JSON.
La respuesta honesta para la mayoría de los nuevos proyectos: usa lo que espera el ecosistema del lenguaje principal. Rust espera TOML. Las herramientas de Python esperan TOML o YAML. Node.js espera JSON. Si estás escribiendo algo independiente de lenguaje, usar TOML para configuraciones editadas por humanos y JSON para configuraciones generadas por máquinas o consumidas por máquinas es una división razonable por defecto.
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta se agregó el 15 de junio de 2026
