¿Qué es TOML?
TOML — Tom's Obvious, Minimal Language (El Lenguaje Obvio y Mínimo de Tom) — es un formato de archivo de configuración creado por Tom Preston-Werner (cofundador de GitHub) en 2013. Su objetivo de diseño es ser un formato mínimo que se mapea inequívocamente a una tabla hash — un archivo de configuración obvio de leer y escribir, con tipado explícito y semántica clara que elimina los comportamientos sorprendentes de YAML e INI.
TOML alcanzó la versión 1.0.0 en enero de 2021. Es ahora el formato de configuración predeterminado del ecosistema Rust (Cargo.toml), usado por herramientas de empaquetado Python (pyproject.toml), y adoptado por muchos proyectos Go, PHP y JavaScript.
Filosofía de Diseño
TOML fue construido con restricciones de diseño específicas:
- Obvio: un humano que lee un archivo TOML debe entender inmediatamente la estructura.
- Mínimo: solo las características necesarias para la configuración.
- Inequívoco: cada archivo TOML se mapea a exactamente una estructura de datos sin sorpresas de coerción de tipos.
TOML evita deliberadamente la complejidad de YAML (especificación de 200+ páginas) y la falta de comentarios de JSON.
Sintaxis Básica
# Comentario TOML
# Pares clave-valor (tabla de nivel superior)
nombre = "KaijuConverter"
version = "2.1.0"
activo = true
precio = 9.99
max_conexiones = 100
# Fechas y horas (RFC 3339)
creado_en = 2024-01-15T10:30:00Z
fecha_local = 2024-01-15 # fecha sin hora
hora_local = 10:30:00 # hora sin fecha
# Cadena básica multilínea
descripcion = """
Esta es una cadena
multilínea.
"""
# Cadena literal multilínea (sin escape)
regex = '''
^[a-z]+$
'''
Tablas (Objetos)
Las tablas son el equivalente TOML de los objetos/diccionarios:
[base_de_datos]
host = "localhost"
puerto = 5432
nombre = "kaijudb"
ssl = true
[base_de_datos.pool]
minimo = 2
maximo = 20
timeout = 30
[servidor]
host = "0.0.0.0"
puerto = 8080
Las claves con puntos proporcionan una abreviatura para tablas anidadas:
base_de_datos.host = "localhost"
base_de_datos.puerto = 5432
Arrays de Tablas
[[dobles_corchetes]] crean arrays de tablas — la forma TOML de representar una lista de objetos:
[[servidores]]
nombre = "web-01"
ip = "192.168.1.10"
rol = "primario"
[[servidores]]
nombre = "web-02"
ip = "192.168.1.11"
rol = "replica"
Esto se mapea a un array de objetos servidor.
Tipos de Datos
TOML tiene tipos explícitos e inequívocos:
| Tipo | Ejemplo | Notas |
|---|---|---|
| Cadena | "hola" o 'raw' |
Básica (con escape) o literal (sin escape) |
| Entero | 42, -7, 1_000_000 |
Guiones bajos para legibilidad |
| Flotante | 3.14, 1.0e10, inf, nan |
Double IEEE 754 |
| Booleano | true, false |
Solo minúsculas |
| Fecha y hora | 2024-01-15T10:30:00Z |
RFC 3339; offset, local-datetime, local-date, local-time |
| Array | [1, 2, 3] o ["a", "b"] |
Tipos mixtos permitidos en 1.0 pero no recomendados |
| Tabla inline | {x = 1, y = 2} |
Solo una línea; sin coma final |
Tipos de cadena:
- Cadena básica (
"...") — admite secuencias de escape:\n,\t,\uXXXX,\\,\". - Cadena literal (
'...') — sin escape; lo que escribes es lo que obtienes. - Básica multilínea (
"""...""") — el salto de línea inicial tras las comillas de apertura se elimina. - Literal multilínea (
'''...''') — sin escape, contenido raw.
TOML en la Práctica: Cargo.toml
El manifiesto de paquetes Rust es el archivo TOML más usado del mundo:
[package]
name = "mi-app"
version = "0.1.0"
edition = "2021"
description = "Un convertidor de archivos rápido"
license = "MIT"
[dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
[profile.release]
opt-level = 3
lto = true
strip = true
TOML en Python: pyproject.toml
PEP 518 y PEP 621 estandarizaron pyproject.toml como descriptor de proyecto Python:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "mi-paquete"
version = "1.0.0"
requires-python = ">=3.11"
dependencies = [
"requests>=2.28",
"pydantic>=2.0",
]
[tool.ruff]
line-length = 88
[tool.mypy]
strict = true
TOML vs. YAML vs. INI vs. JSON
| Característica | TOML | YAML | INI | JSON |
|---|---|---|---|---|
| Comentarios | Sí | Sí | Sí | No |
| Tipos explícitos | Sí | Parcial | No | Sí |
| Cadenas multilínea | Sí | Sí | No | Solo escape |
| Estructuras anidadas | Sí (tablas) | Sí | Limitado | Sí |
| Arrays de objetos | Sí ([[]]) |
Sí | No | Sí |
| Fechas/horas | Nativas | Coercionadas | No | No |
| Anclas/alias | No | Sí | No | No |
| Complejidad de spec | Baja | Muy alta | Ninguna | Baja |
| Ambigüedad | Ninguna | Alta | Alta | Ninguna |
| Mejor para | Config | CI/CD, K8s | Config simple | APIs, datos |
Análisis de TOML
Python (stdlib desde Python 3.11):
import tomllib
with open('config.toml', 'rb') as f:
config = tomllib.load(f)
# Para escribir, usa tomli-w (tercero)
import tomli_w
with open('salida.toml', 'wb') as f:
tomli_w.dump(datos, f)
Rust (con serde):
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
nombre: String,
version: String,
}
let config: Config = toml::from_str(toml_str)?;
Conversión de TOML
- TOML → JSON:
yq e -o=json config.toml, Pythonjson.dumps(tomllib.loads(s)). - TOML → YAML:
yq e -o=yaml config.toml. - JSON → TOML:
yq e -o=toml entrada.json. - YAML → TOML:
yq e -o=toml entrada.yaml.
Buenas Prácticas
- Usa TOML para la configuración que los humanos editan — sus tipos explícitos eliminan sorpresas.
- Prefiere encabezados
[tabla]sobre tablas inline profundamente anidadas para legibilidad. - Usa
[[arrays de tablas]]para listas de objetos — más limpio que las secuencias de YAML. - Usa siempre fechas RFC 3339 — los tipos de fecha/hora nativos de TOML evitan la ambigüedad.
- Usa cadenas literales (
'...') para patrones regex, rutas de archivos y cualquier cadena con barras invertidas. - Usa guiones bajos en números para legibilidad:
1_000_000en lugar de1000000. - Valida el esquema con
taplo(kit de herramientas TOML basado en Rust con integración JSON Schema). - Ordena las claves alfabéticamente dentro de las tablas para diffs consistentes.
- No mezcles definición de tabla y asignación de clave-valor en diferentes lugares.
- Prefiere TOML sobre YAML para nuevos proyectos donde no se requieran los idiomas CI/CD de YAML.
Conversiones relacionadas
Conversiones frecuentes del catálogo: