Hvis du har åpnet et Rust-prosjekt, har du møtt TOML. Hvis du har vært borti en Python-pakke som bruker
pyproject.toml, har du brukt det også. TOML — Tom's Obvious Minimal Language —
er konfigurasjonsfil-formatet som stille og rolig vinner over utviklere som er lei av YAMLs mellomrom-
fallgruver og JSONs avvisning av kommentarer. Skapt av Tom Preston-Werner, medgrunnlegger av GitHub, ble TOML
designet rundt én idé: et konfigurasjonsformat bør være så åpenbart at du kan lese det uten en spesifikasjon.
La oss se om det innfrir det løftet.
Hva Nøyaktig Er TOML?
TOML er et konfigurasjonsfil-format med tre eksplisitte designmål, stavet ut rett øverst i den offisielle spesifikasjonen: det skal være åpenbart å lese, minimalt i kompleksitet og kartlegge entydig til en hashtabell (en ordbok/kart i de fleste språk). Det tredje målet er det viktigste — alle gyldige TOML-filer har nøyaktig ett korrekt parseresultat. Ingen overraskende typetvang, ingen YAML-lignende boolske landminer, ingen tvetydighet om hvorvidt en verdi er en streng eller et tall.
Formatet låner seksjonsoverskrift-stilen fra gamle INI-filer men legger til riktige typer, matriser og nestede tabeller på toppen. Resultatet er noe som føles kjent for alle som har redigert en konfigurasjonsfil før, men med nok struktur til at en parser kan gi deg en ekte typet datamodell ut av det. Versjon 1.0.0 av spesifikasjonen ble utgitt i januar 2021 etter års raffinement — du kan bla gjennom hele TOML-spesifikasjonen på GitHub hvis du vil grave inn i grensetilfellene.
Grunnleggende: Nøkkel-verdi-par og Kommentarer
En TOML-fil er bygget opp av nøkkel-verdi-par. Nøkler og verdier er atskilt med =,
og kommentarer starter med #. Enkelt.
# Cargo.toml — Rust package manifest
[package]
name = "image-resizer"
version = "0.4.2"
edition = "2021"
authors = ["Ada Lovelace <[email protected]>"]
description = "Fast image resizing with Lanczos3 resampling"
license = "MIT"
repository = "https://github.com/example/image-resizer"
# Integers, floats, booleans — all native types
max_threads = 8
quality_default = 0.85
verbose_logging = falseIngen anførsels-tegn nødvendig på de fleste nøkler. Verdier er typede — 8 er et heltall, 0.85
er en flyt, false er en boolsk. Ingen gjetning, ingen implisitt tvang basert på hvordan verdien ser ut.
Dette er det hverdagslige TOML du vil skrive 90 % av tiden.
Strengtyper: Grunnleggende, Literal og Flerlinjete
TOML har fire strengtyper. Dette dekker alle virkelige tilfeller rent:
# Basic strings — double quotes, support escape sequences
greeting = "Hello, \nworld!"
path = "C:\\Users\\ada\\Documents"
# Literal strings — single quotes, no escape processing at all
regex_pattern = '\d{4}-\d{2}-\d{2}'
windows_path = 'C:\Users\ada'
# Multiline basic string — triple double quotes
sql_query = """
SELECT user_id, email, created_at
FROM users
WHERE active = true
AND created_at > '2024-01-01'
ORDER BY created_at DESC
"""
# Multiline literal string — triple single quotes, no escapes
shell_script = '''
#!/bin/bash
echo "Deploying $APP_NAME to $ENV"
kubectl apply -f k8s/
'''Literal-strengtypen ('enkle anførsels-tegn') er den folk glemmer eksisterer, og den er
genuint nyttig — regex-mønstre og Windows-baner er mye renere uten escape-dobling. Velg den anførsels-tegn-stilen som
betyr at du skriver færre backslash-er.
Tall, Booleaner og Datetider
TOMLs native typer dekker alt du faktisk ville legge inn i en konfigurasjonsfil. Spesielt har det førsteklasses datetime-støtte — noe YAML teknisk har men håndterer inkonsekvent på tvers av parsere.
# Integers — underscores allowed as separators (like numeric literals in code)
max_connections = 1_000_000
port = 5432
hex_color = 0xFF6B6B # hex prefix supported
octal_permissions = 0o755 # octal prefix supported
# Floats
pi = 3.14159265
compression_ratio = 1.5e-3
infinity_val = inf # special values: inf, -inf, nan
# Booleans — lowercase only (not True, TRUE, yes, on)
ssl_enabled = true
dry_run = false
# Datetimes — RFC 3339 format
created_at = 2024-03-15T09:30:00Z
updated_at = 2024-03-15T14:22:10+05:30
log_date = 2024-03-15 # local date (no time)
backup_time = 03:00:00 # local time (no date)true og false —
ikke True, TRUE, yes, on, eller noen av de andre variantene
YAML 1.1 godtar. Dette er tilsiktet. Hvis du trenger strengen "true", sett den i anførsels-tegn.Tabeller: INI-Lignende Seksjonsoverskrifter
Tabeller i TOML er definert med [overskrift]-syntaks. Alt under en overskrift tilhører
den tabellen inntil neste overskrift vises. Dette er funksjonen som gjør TOML kjent — det er
i bunn og grunn INI-filer men med typer.
[database]
host = "db.internal"
port = 5432
name = "app_production"
pool_size = 20
[database.credentials]
username = "app_user"
# Don't put real passwords here — use env vars or a secrets manager
password_env = "DB_PASSWORD"
[server]
host = "0.0.0.0"
port = 8080
workers = 4
[server.tls]
enabled = true
cert_file = "/etc/ssl/certs/app.crt"
key_file = "/etc/ssl/private/app.key"Prikk-overskrifter som [database.credentials] lager nestede tabeller. Det analyserte resultatet
er akkurat hva du ville forvente: et database-objekt med et nestet credentials-objekt.
Du kan også skrive inline-tabeller for enkle tilfeller — mer om det nedenfor.
Matriser og Matrise av Tabeller
Matriser i TOML bruker hakeparenteser og kan spenne over flere linjer. Den virkelig særegne TOML-funksjonen
er Matrise av Tabeller — definert med doble hakeparenteser [[overskrift]]. Dette er TOMLs
svar på "hvordan uttrykker jeg en liste med objekter?" uten at det ser ut som JSON.
# Regular arrays — can be split across lines, trailing comma is fine
allowed_origins = [
"https://app.example.com",
"https://admin.example.com",
"http://localhost:3000",
]
supported_formats = ["jpeg", "png", "webp", "avif"]
retry_delays_ms = [100, 250, 500, 1000, 2000]
# Array of Tables — [[double brackets]]
# Each [[servers]] header appends a new object to the servers array
[[servers]]
name = "web-01"
ip = "10.0.1.10"
role = "primary"
tags = ["web", "prod"]
[[servers]]
name = "web-02"
ip = "10.0.1.11"
role = "replica"
tags = ["web", "prod"]
[[servers]]
name = "db-01"
ip = "10.0.2.10"
role = "primary"
tags = ["database", "prod"]Den [[servers]]-syntaksen parses til en matrise av tre objekter — tilsvarende
"servers": [{...}, {...}, {...}] i JSON. Det er verbose sammenlignet med JSON-matriser av objekter,
men fordelen er lesbarhet når hvert element har mange felt. Du kan se dette mønsteret mye i
Cargo.toml-manifester
for å definere flere binære mål, eksempler og bench-oppføringer.
Inline-tabeller: Kompakte Énlinjere
Når en tabell bare har et par felt og du ikke vil ha en hel seksjonsoverskrift for det, lar inline-tabeller deg skrive det på én linje:
[build]
# Inline table — must stay on one line
target = { arch = "x86_64", os = "linux", libc = "musl" }
# Equivalent to writing:
# [build.target]
# arch = "x86_64"
# os = "linux"
# libc = "musl"
[feature_flags]
auth = { enabled = true, rollout_pct = 100 }
search = { enabled = true, rollout_pct = 50 }
beta = { enabled = false, rollout_pct = 0 }Inline-tabeller må bli på én linje og kan ikke utvides senere med en [overskrift].
Bruk dem for små, sammenhengende verdigrupper — de er flotte for ting som koordinatpar, byggemål
eller enkle flaggkonfigurasjoner. Ikke bruk dem når du har mer enn tre eller fire felt; på det punktet leser en vanlig
tabell bedre.
TOML i den Virkelige Verden
TOML har skåret ut en sterk nisje i Rust- og Python-økosystemene, og vinner terreng andre steder. Her er hvor du vil møte det daglig:
- Rust — Cargo.toml: Hvert Rust-prosjekt har en. Definerer pakke-metadata, avhengigheter, funksjoner og byggemål. Cargo-manifestreferansen er den mest detaljerte virkelige TOML-bruksguiden du finner.
- Python — pyproject.toml: PEP 518 og PEP 621 standardiserte TOML som Python-prosjektmetadata-formatet. Poetry, Hatch, PDM og setuptools leser alle fra det.
- Deno: Deno-konfigurasjonsfilen støtter TOML i tillegg til JSON.
- Hugo: Hugo statisk nettstedsgenerator godtar TOML som konfig- og frontmatter-format — du ser det mellom
+++-avgrensere øverst i Markdown-filer. - uv: Den raske Python-pakkebehandleren fra Astral bruker pyproject.toml for all konfigurasjon, noe som gjør TOML til de facto standard for nytt Python-verktøy.
Hvis du trenger å konvertere en eksisterende konfig mellom formater, håndterer TOML til JSON og JSON til TOML- konverterne den strukturelle kartleggingen for deg. Eller bruk TOML-formatering-verktøyet til å rydde opp inkonsekvent mellomrom i en eksisterende fil, og TOML-validator-verktøyet til å fange syntaksfeil før de dukker opp i produksjon.
Parse TOML i Python
Siden Python 3.11 inkluderer standardbiblioteket
tomllib
— ingen ekstern avhengighet nødvendig. For Python 3.9 og 3.10 har
tomli-tilbakeporten
et identisk API, slik at du kan bytte mellom dem med ett enkelt importaliasert.
import sys
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib # pip install tomli
# tomllib only reads binary mode — open with "rb"
with open("pyproject.toml", "rb") as f:
config = tomllib.load(f)
# Types match TOML exactly: str, int, float, bool, datetime, list, dict
project_name = config["project"]["name"] # str
python_requires = config["project"]["requires-python"] # str
dependencies = config["project"]["dependencies"] # list[str]
print(f"Project: {project_name}")
print(f"Requires Python: {python_requires}")
print(f"Dependencies ({len(dependencies)}):")
for dep in dependencies:
print(f" {dep}")
# Parse from a string with tomllib.loads()
raw = """
[server]
host = "localhost"
port = 8080
debug = true
"""
server_config = tomllib.loads(raw)
print(server_config["server"]["port"]) # 8080 (int, not "8080")Merk at tomllib.load() krever binærmodus ("rb"). Dette er tilsiktet —
TOML krever UTF-8-koding, og å åpne i binærmodus lar parseren håndtere kodingskontrollen selv.
Det er en liten fallgruve som tar folk første gang.
Parse TOML i Rust
I Rust er toml-crate
standardvalget. Den integrerer tett med serde, slik at du kan deserialisere direkte til
dine egne structs med minimal kode:
use serde::Deserialize;
use std::fs;
#[derive(Debug, Deserialize)]
struct AppConfig {
server: ServerConfig,
database: DatabaseConfig,
feature_flags: FeatureFlags,
}
#[derive(Debug, Deserialize)]
struct ServerConfig {
host: String,
port: u16,
workers: usize,
}
#[derive(Debug, Deserialize)]
struct DatabaseConfig {
host: String,
port: u16,
name: String,
pool_size: u32,
}
#[derive(Debug, Deserialize)]
struct FeatureFlags {
enable_beta: bool,
max_upload_mb: u32,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let raw = fs::read_to_string("config.toml")?;
let config: AppConfig = toml::from_str(&raw)?;
println!("Server: {}:{}", config.server.host, config.server.port);
println!("DB pool size: {}", config.database.pool_size);
println!("Beta enabled: {}", config.feature_flags.enable_beta);
Ok(())
}Legg til toml = "0.8" og serde = { version = "1", features = ["derive"] }
i [dependencies] i Cargo.toml og du er klar. Serde derive-makroene håndterer all
feltmapping. Hvis struct-feltnavnene dine bruker snake_case men TOML-nøklene bruker kebab-case, legg til
#[serde(rename_all = "kebab-case")] på struct-nivå og alt mapper automatisk.
TOML vs YAML vs JSON — Når Velger Man Hva
Dette spørsmålet dukker opp på hvert nytt prosjekt. Her er den ærlige gjennomgangen:
- TOML: Best for konfigurasjonsfiler som mennesker skriver og vedlikeholder, der typede verdier er viktige og nesting er grunn til moderat. Sødøme sted: appkonfigurasjoner, byggemanifester, verktøyinnstillinger. Bryter sammen ved dyp nesting — 4+ nivåer blir vanskelig med gjentatte seksjonsoverskrifter.
- YAML: Best når du skriver strukturerte data med mange lister-av-objekter (Kubernetes-manifester, GitHub Actions-arbeidsflyter). Flerlinjet strengstøtte er genuint bedre enn TOMLs. Ulempen: mellomrom-sensitivitet og YAML 1.1-typetvang skaper reelle feil i praksis.
- JSON: Best for maskin-til-maskin datautveksling, API-er og når du trenger bredest mulig verktøykjedesupport. Ikke flott for menneskelig vedlikeholdt konfig — ingen kommentarer, og strengescaping er kjedelig.
En Ekte pyproject.toml
For å sette alt sammen, her er en realistisk pyproject.toml for et Python-bibliotek —
den typen du ville finne på et moderne åpen kildekode-prosjekt. Legg merke til hvordan formatet bærer mye strukturert
informasjon mens det fortsatt er lett å skumme:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "httpx-cache"
version = "1.2.0"
description = "Transparent HTTP caching layer for httpx"
readme = "README.md"
license = { file = "LICENSE" }
requires-python = ">=3.9"
authors = [
{ name = "Ada Lovelace", email = "[email protected]" },
]
keywords = ["http", "cache", "httpx", "async"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"httpx>=0.25.0",
"anyio>=4.0.0",
]
[project.optional-dependencies]
redis = ["redis>=5.0.0"]
dev = [
"pytest>=7.4.0",
"pytest-asyncio>=0.23.0",
"coverage[toml]>=7.3.0",
"ruff>=0.1.0",
"mypy>=1.7.0",
]
[project.urls]
Homepage = "https://github.com/example/httpx-cache"
Changelog = "https://github.com/example/httpx-cache/blob/main/CHANGELOG.md"
[tool.ruff]
line-length = 100
target-version = "py39"
[tool.ruff.lint]
select = ["E", "F", "I", "UP"]
[tool.mypy]
strict = true
python_version = "3.9"
[tool.coverage.run]
source = ["httpx_cache"]
branch = true
[tool.coverage.report]
fail_under = 90Dette er ekte TOML som gjør ekte arbeid. Hver [tool.x]-seksjon er et separat navnerom
for et annet verktøy — ruff, mypy, coverage — alle lever i én fil uten å tråkke på hverandre.
Ingen dyp nesting nødvendig, alt er lesbart med ett blikk.
Oppsummering
TOML innfrir løftet: lesbart, entydig og rent typet. Hvis du starter et nytt prosjekt i Rust, Python eller Go, er TOML verdt å bruke som standard for konfigurasjonsfiler — spesielt filer som vil bli committed til kildekontroll og redigert av flere. Mangelen på mellomromsensitivitet alene gjør det til en lettelse sammenlignet med YAML. For å jobbe med TOML-filer direkte i nettleseren din, håndterer TOML-formatering og TOML-validator-verktøyene de vanligste oppgavene. Og hvis du migrerer et eksisterende prosjekt fra JSON eller trenger å bringe TOML inn i en JSON-basert pipeline, dekker TOML til JSON og JSON til TOML-konverterne det.