YAML, JSON, TOML, and XML each have different strengths. YAML excels at human-written config. JSON excels at machine-to-machine APIs. TOML excels at application config files. XML excels at document-centric data with mixed content.
| Item | Syntax / Value | Description |
|---|---|---|
| YAML comments | # comment anywhere | JSON has no comments — YAML wins for config files |
| YAML multi-line | | and > block scalars | JSON requires \n escapes — YAML is far more readable |
| YAML anchors | & and * for reuse | JSON has no reuse mechanism — copy/paste only |
| YAML types | auto-detects dates, booleans, nulls | JSON has 6 explicit types — more predictable |
| YAML ambiguity | yes/no/on/off parsed as boolean in 1.1 | JSON booleans are always true/false — unambiguous |
| YAML security | Never yaml.load() untrusted input | JSON.parse() is safe — YAML can execute code |
| YAML tooling | Less universal than JSON | JSON has universal library support in every language |
| JSON compactness | No whitespace required | YAML requires indentation — more verbose |
| JSON APIs | Standard for REST APIs | YAML not commonly used for API responses |
| JSON in YAML | All valid JSON is valid YAML | Migration path: JSON → YAML is always valid |
| TOML sections | [section] / [[array-of-tables]] | Clear section syntax — better than YAML for app config |
| TOML types | Explicit: 2026-01-01 = date literal | TOML has native date/time types |
| TOML use case | Cargo.toml, pyproject.toml, config.toml | TOML is Rust/Python ecosystem standard |
| XML verbosity | <tag>value</tag> much more verbose | JSON/YAML far more compact for data |
| XML mixed content | <p>Text with <em>emphasis</em></p> | XML handles mixed text/element content |
| XML namespaces | Prevent name collisions | No equivalent in JSON/YAML |
| XML transforms | XSLT — powerful transformation | No equivalent in JSON/YAML |
| Use JSON when | Machine-to-machine APIs, web responses | Universal, fast, unambiguous |
| Use YAML when | Config files, CI/CD, Kubernetes | Human-readable, supports comments and anchors |
| Use TOML when | Application config files (.toml) | Clear, unambiguous, typed |
| Use XML when | Document data, enterprise integration | Namespaces, mixed content, XSLT transforms |
| yq tool | yq '.key' file.yaml | Like jq but for YAML — process YAML on command line |
# ── Same data in YAML, JSON, TOML, and XML ──────────────────
# YAML (config/DevOps best choice — human-written)
---
database:
host: localhost
port: 5432
name: mywebuniversity
username: admin
pool:
min: 2
max: 10
ssl:
enabled: true
verify: true
server:
host: 0.0.0.0
port: 8080
workers: 4
timeout: 30
cors:
origins: [https://mywebuniversity.com, http://localhost:3000]
methods: [GET, POST, PUT, DELETE]
logging:
level: info
format: json
file: /var/log/app.log
# ── Equivalent JSON (API responses — universal) ──────────────
{
"database": {
"host": "localhost",
"port": 5432,
"name": "mywebuniversity",
"username": "admin",
"pool": { "min": 2, "max": 10 },
"ssl": { "enabled": true, "verify": true }
},
"server": {
"host": "0.0.0.0",
"port": 8080,
"workers": 4,
"timeout": 30,
"cors": {
"origins": ["https://mywebuniversity.com", "http://localhost:3000"],
"methods": ["GET", "POST", "PUT", "DELETE"]
}
},
"logging": { "level": "info", "format": "json", "file": "/var/log/app.log" }
}
# ── Equivalent TOML (application config best choice) ─────────
[database]
host = "localhost"
port = 5432
name = "mywebuniversity"
username = "admin"
[database.pool]
min = 2
max = 10
[database.ssl]
enabled = true
verify = true
[server]
host = "0.0.0.0"
port = 8080
workers = 4
timeout = 30
[server.cors]
origins = ["https://mywebuniversity.com", "http://localhost:3000"]
methods = ["GET", "POST", "PUT", "DELETE"]
[logging]
level = "info"
format = "json"
file = "/var/log/app.log"
# ── yq command-line tool ─────────────────────────────────────
# Install: snap install yq / brew install yq / wget yq binary
yq '.database.host' config.yaml # extract value
yq '.server.port = 9090' config.yaml # update value
yq '.server.workers' config.yaml # get workers
yq 'del(.logging)' config.yaml # delete key
yq '.database | keys' config.yaml # list keys
yq -o json '.' config.yaml # convert to JSON
yq -P '.' config.json # convert JSON to YAML (pretty)
yq eval-all 'select(fileIndex==0) * select(fileIndex==1)' base.yaml override.yaml # merge files