Docker uses YAML. Rust uses TOML. REST APIs use JSON. Akka uses HOCON. Each format solves different problems.

Here’s the same configuration in all four formats to see the differences:

JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "server": {
    "host": "0.0.0.0",
    "port": 8080,
    "workers": 4,
    "timeout": 30
  },
  "database": {
    "host": "localhost",
    "port": 5432,
    "name": "myapp",
    "pool_size": 20,
    "ssl": true
  },
  "features": {
    "caching": true,
    "logging": true,
    "monitoring": false
  }
}

YAML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server:
  host: 0.0.0.0
  port: 8080
  workers: 4
  timeout: 30

database:
  host: localhost
  port: 5432
  name: myapp
  pool_size: 20
  ssl: true

features:
  caching: true
  logging: true
  monitoring: false

TOML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[server]
host = "0.0.0.0"
port = 8080
workers = 4
timeout = 30

[database]
host = "localhost"
port = 5432
name = "myapp"
pool_size = 20
ssl = true

[features]
caching = true
logging = true
monitoring = false

HOCON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Server configuration
server {
  host = "0.0.0.0"
  port = 8080
  workers = 4
  timeout = 30
}

// Database settings
database {
  host = localhost
  port = 5432
  name = myapp
  pool_size = 20
  ssl = true
}

// Feature flags
features {
  caching = true
  logging = true
  monitoring = false
}

Now let’s break down each format.


JSON: Universal Data Format

Best for: APIs, data exchange, browser communication

Pros:

  • Universal support across all languages
  • Fast parsing speed
  • Strict syntax reduces errors
  • Perfect for machine-to-machine communication

Cons:

  • No comment support
  • Verbose with quotes and braces
  • Trailing commas break parsing
  • Multi-line strings need escaping

Real-world usage:

  • REST APIs and web services
  • Node.js package.json
  • MongoDB documents
  • Browser storage (localStorage)

When to use: Data exchange between systems, APIs, any machine-generated configs.


YAML: Human-Readable Format

Best for: Docker, Kubernetes, CI/CD pipelines

Pros:

  • Highly readable with minimal syntax
  • Supports comments (#)
  • Excellent for complex nested structures
  • Multi-line strings without escaping
  • Industry standard for DevOps

Cons:

  • Indentation-sensitive (spaces matter)
  • Slower parsing than JSON
  • Different parsers may behave differently
  • Security risks if not parsed safely

Real-world usage:

  • Docker Compose files
  • Kubernetes manifests
  • GitHub Actions workflows
  • Ansible playbooks
  • OpenAPI specifications

When to use: Container orchestration, CI/CD pipelines, complex configurations with deep nesting.


TOML: Configuration Specialist

Best for: Application configs, build tools, package manifests

Pros:

  • Clean, minimal syntax
  • Supports comments (#)
  • Explicit data types (string, integer, float, date)
  • Unambiguous parsing
  • Native date/time support
  • Better error messages than JSON

Cons:

  • Smaller ecosystem than JSON/YAML
  • Complex nesting can get verbose
  • Less familiar to most developers

Real-world usage:

  • Rust Cargo.toml
  • Python pyproject.toml
  • Application configuration files
  • Build tool settings

When to use: Human-edited configs that need comments, Rust/Python projects, settings that change frequently.


HOCON: Flexible JSON Superset

Best for: JVM applications, complex configs, microservices

Pros:

  • Superset of JSON (all JSON is valid HOCON)
  • Supports comments (# or //)
  • Unquoted keys for cleaner syntax
  • Variable substitutions and includes
  • Can merge configurations
  • Path expressions for navigation

Cons:

  • Mainly JVM ecosystem (Scala, Java)
  • Less adoption outside JVM world
  • More complex than simple formats
  • Requires specific parsers

Real-world usage:

  • Akka framework
  • Play Framework
  • Lightbend/Typesafe projects
  • Scala applications
  • JVM microservices

When to use: JVM applications, complex configs needing modularity, projects requiring config inheritance and substitutions.


Technical Comparison

Feature Matrix

Feature JSON YAML TOML HOCON
Comments ❌ No ✅ Yes (#) ✅ Yes (#) ✅ Yes (# or //)
Data Types String, Number, Boolean, Array, Object, Null String, Number, Boolean, List, Dictionary, Custom String, Integer, Float, Boolean, Date, Array, Table All JSON types + Substitutions
Nesting ✅ Unlimited ✅ Unlimited ✅ Unlimited ✅ Unlimited
Multi-line Strings ❌ Escaped ✅ Native ✅ Native (""") ✅ Native
Arrays ✅ Yes ✅ Yes ✅ Yes ✅ Yes
Date/Time Types ❌ No ✅ Yes ✅ Yes ❌ No (use strings)
Whitespace Sensitive ❌ No ✅ Yes ❌ No ❌ No
Trailing Commas ❌ Error ✅ Allowed ✅ Allowed ✅ Allowed
Parser Speed ⚡ Very Fast 🐢 Slower ⚡ Fast ⚡ Fast
Ecosystem Size 🌟 Massive 🌟 Large 📊 Growing 📊 JVM-focused

Performance Benchmarks

Parsing 10,000 configuration files (1KB each):

Format Parse Time Files/Second Relative Speed
JSON 0.34 seconds ~29,400 1.0x (baseline)
HOCON 0.42 seconds ~23,800 0.81x
TOML 0.89 seconds ~11,200 0.38x
YAML 1.24 seconds ~8,000 0.27x

Note: For most applications, configuration files are parsed once at startup, making these differences negligible.

Error Message Quality

JSON error:

1
SyntaxError: Unexpected token } in JSON at position 47

YAML error:

1
YAMLException: bad indentation of a mapping entry at line 5, column 3

TOML error:

1
Error: Expected string, got integer for key 'port' at line 12, column 8

HOCON error:

1
Error: Could not resolve substitution to a value: ${database.host} at line 15

TOML and HOCON provide specific error messages, making debugging easier.


Quick Decision Guide

Use JSON if:

  • Building REST APIs
  • Exchanging data between services
  • Working with JavaScript in browsers
  • Need maximum parsing speed
  • Want universal compatibility

Use YAML if:

  • Configuring Docker or Kubernetes
  • Setting up CI/CD pipelines
  • Need complex nested structures
  • Human readability is critical
  • Working with DevOps tools

Use TOML if:

  • Building Rust or Python projects
  • Need comments in config files
  • Want unambiguous syntax
  • Configuration changes frequently
  • Date/time values are important

Use HOCON if:

  • Building JVM applications (Akka, Play Framework)
  • Need variable substitutions and includes
  • Want configuration inheritance
  • Complex microservices with shared configs
  • Scala or Java projects

Real-World Usage Patterns

Web Application Stack:

  • Docker Compose: YAML (orchestration)
  • Application config: TOML (human-edited settings)
  • package.json: JSON (package manifest)
  • JVM services: HOCON (complex configs)

Python Project:

  • pyproject.toml: TOML (project metadata)
  • GitHub Actions: YAML (CI/CD)
  • API responses: JSON (data exchange)

Microservices:

  • Service communication: JSON
  • Kubernetes manifests: YAML
  • Application configs: TOML
  • JVM microservices: HOCON

Parsing Examples

JavaScript:

1
2
3
4
5
6
7
8
9
10
11
// JSON (built-in)
const config = JSON.parse(fs.readFileSync('config.json'));

// YAML: npm install js-yaml
const config = yaml.load(fs.readFileSync('config.yml'));

// TOML: npm install toml
const config = toml.parse(fs.readFileSync('config.toml'));

// HOCON: npm install config (for Node.js)
const config = require('config'); // Reads from config/default.conf

Python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import json, yaml, tomli
from pyhocon import ConfigFactory

# JSON (built-in)
config = json.load(open('config.json'))

# YAML: pip install pyyaml
config = yaml.safe_load(open('config.yml'))

# TOML: pip install tomli
config = tomli.load(open('config.toml', 'rb'))

# HOCON: pip install pyhocon
config = ConfigFactory.parse_file('application.conf')

Converting Between Formats

Using remarshal (Python tool):

1
2
3
4
5
6
pip install remarshal

# Convert between any formats
remarshal -if json -of yaml config.json config.yml
remarshal -if yaml -of toml config.yml config.toml
remarshal -if toml -of json config.toml config.json

Watch out for:

  • Comments are lost when converting to JSON
  • HOCON substitutions need to be resolved before converting
  • Data types may need manual adjustment
  • TOML dates need special handling in JSON/YAML

Common Pitfalls

JSON:

  • Trailing commas break parsing
  • No comments allowed
  • Multi-line strings are messy
  • Fix: Use a linter

YAML:

  • Indentation errors (spaces matter!)
  • Boolean confusion (no becomes false)
  • Fix: Use consistent 2 or 4 spaces

TOML:

  • Duplicate keys cause errors
  • Complex nesting gets confusing
  • Fix: Keep structure simple

HOCON:

  • Substitution errors can be cryptic
  • More complex than simple formats
  • Fix: Test config loading early, use fallback values

Migration Guide

Quick migration steps:

  1. Audit your configs - List all JSON, YAML, TOML, HOCON files
  2. Categorize by use - APIs stay JSON, orchestration stays YAML
  3. Migrate one at a time - Start with most problematic file
  4. Add comments - Document why settings exist (TOML/YAML/HOCON)
  5. Test thoroughly - Ensure parsing works correctly

Simple migration example:

1
2
3
4
5
6
7
8
9
# Backup
cp config.json config.json.backup

# Convert
remarshal -if json -of toml config.json config.toml

# Add comments explaining settings
# Update code to parse TOML instead of JSON
# Test and deploy

Summary

Key Takeaways:

  1. JSON for machine-to-machine communication and APIs
  2. YAML for complex configs and DevOps tools
  3. TOML for human-edited application configurations
  4. HOCON for JVM applications with complex config needs

Migration advice:

  • Don’t migrate everything at once
  • Start with files that cause the most confusion
  • Keep JSON for APIs and data exchange
  • Use TOML for configs that need comments
  • Follow ecosystem conventions (YAML for Docker, TOML for Rust, HOCON for Akka)

The right format depends on your specific needs. Consider who reads and writes the file, how complex the data is, and what your ecosystem uses.


Head-to-Head Comparisons

HOCON vs YAML

HOCON and YAML both support comments and human-readable syntax, but serve different ecosystems.

Aspect HOCON YAML
Primary Use JVM applications (Akka, Play) DevOps tools (Docker, Kubernetes)
Syntax Brace-based, JSON superset Indentation-based
Comments # and // # only
Variable Substitution ✅ Native (${var}) ❌ No (needs templating)
Config Includes ✅ Built-in ❌ No
Whitespace Sensitive ❌ No ✅ Yes
Ecosystem Scala, Java Universal

Choose HOCON over YAML when:

  • Building Scala/Java applications with Akka or Play Framework
  • Need configuration inheritance and variable substitution
  • Want to include shared config files

Choose YAML over HOCON when:

  • Working with Docker, Kubernetes, or GitHub Actions
  • Team is more familiar with YAML syntax
  • Using tools that expect YAML (most DevOps tools)

HOCON vs JSON

HOCON is a superset of JSON, meaning all valid JSON is valid HOCON. HOCON adds features JSON lacks.

Aspect HOCON JSON
Comments ✅ Yes (#, //) ❌ No
Trailing Commas ✅ Allowed ❌ Error
Unquoted Keys ✅ Yes ❌ Must quote
Variable Substitution ✅ Yes (${var}) ❌ No
Config Includes ✅ Yes ❌ No
Multi-line Strings ✅ Yes ❌ Escaped only
Ecosystem JVM-focused Universal

Choose HOCON over JSON when:

  • Need comments in configuration files
  • Want cleaner syntax without excessive quotes
  • Building JVM applications requiring config inheritance
  • Complex configs with shared values

Choose JSON over HOCON when:

  • Building REST APIs for data exchange
  • Need maximum parsing speed
  • Working in browser/JavaScript environments
  • Want universal language support

TOML vs YAML

TOML and YAML are both human-friendly formats, but with different design philosophies.

Aspect TOML YAML
Syntax Style INI-like sections Indentation-based
Whitespace Sensitive ❌ No ✅ Yes
Date/Time Types ✅ Native ✅ Via tags
Explicit Types ✅ Very explicit ⚠️ Can be ambiguous
Parsing Speed ⚡ Faster 🐢 Slower
Error Messages ✅ Clear ⚠️ Can be cryptic
Ecosystem Rust, Python DevOps, Kubernetes

Choose TOML over YAML when:

  • Building Rust applications (Cargo.toml)
  • Creating Python projects (pyproject.toml)
  • Want unambiguous parsing (no “Norway problem”)
  • Need clear error messages

Choose YAML over TOML when:

  • Configuring Docker Compose or Kubernetes
  • Setting up CI/CD pipelines (GitHub Actions, GitLab CI)
  • Complex nested structures are needed
  • Working with DevOps tooling

TOML vs JSON

TOML is designed for human-edited configs, while JSON excels at machine-to-machine communication.

Aspect TOML JSON
Comments ✅ Yes (#) ❌ No
Date/Time Types ✅ Native ❌ Strings only
Readability ✅ Very clean ⚠️ Verbose
Trailing Commas ✅ Allowed ❌ Error
Parsing Speed ⚡ Fast ⚡ Faster
Browser Support ❌ Needs library ✅ Native
Ecosystem Rust, Python Universal

Choose TOML over JSON when:

  • Need comments in config files
  • Human-edited configuration
  • Rust/Python projects (Cargo.toml, pyproject.toml)
  • Date/time values are important

Choose JSON over TOML when:

  • Building APIs for data exchange
  • Need browser-native parsing
  • Machine-generated configurations
  • Maximum cross-platform compatibility

JSON vs YAML

JSON is strict and fast, YAML is flexible and readable.

Aspect JSON YAML
Comments ❌ No ✅ Yes (#)
Syntax Braces and brackets Indentation-based
Whitespace Sensitive ❌ No ✅ Yes
Parsing Speed ⚡ Very fast 🐢 Slower
Multi-line Strings ❌ Escaped ✅ Native (\|, >)
Browser Support ✅ Native ❌ Needs library
Use Case APIs, data exchange Config files, DevOps

Choose JSON over YAML when:

  • Building REST APIs
  • Data exchange between services
  • Browser JavaScript applications
  • Need strictest parsing

Choose YAML over JSON when:

  • Configuring Docker, Kubernetes, or CI/CD
  • Need comments in config files
  • Complex nested structures
  • Human readability is priority

YAML vs TOML

Both support comments, but differ in structure and ecosystem.

Aspect YAML TOML
Indentation ✅ Required ❌ Not required
Sections Implicit nesting Explicit [section]
Parsing Speed 🐢 Slower ⚡ Faster
Error Clarity ⚠️ Can be cryptic ✅ Clear messages
Type Ambiguity ⚠️ Yes (“Norway problem”) ✅ No
Deep Nesting ✅ Natural ⚠️ Gets verbose

Choose YAML over TOML when:

  • Using Docker, Kubernetes, or Ansible
  • Deep nesting is common
  • Team knows YAML well

Choose TOML over YAML when:

  • Want explicit, unambiguous syntax
  • Rust or Python projects
  • Flat/shallow configuration structures

Building scalable systems? Check out these related posts:

References: