Native TOML 1.0 parser and writer for Mojo
Status: ๐ v0.5.0 - TOML 1.0 Complete + Partial 1.1 (168 tests passing)
mojo-toml enables native TOML parsing in Mojo without Python dependencies. Parse configuration files, project settings, and structured data with a clean, type-safe API.
Key features:
- โ TOML 1.0 compliant - full specification support
- โ
Array of tables -
[[section]]syntax for repeated table arrays - โ
Alternative number bases - hex (
0xDEAD), octal (0o755), binary (0b1101) - โ TOML writer - serialize Dict back to TOML format with round-trip fidelity
- โ Nested structures - dotted keys and table headers
- โ 168 comprehensive tests - parser (127) + writer (41)
- โ Zero Python dependencies - pure native Mojo implementation
Create a TOML file (e.g examples/quickstart.toml):
# Application configuration
[app]
name = "QuickStart"
version = "1.0.0"
debug = false
[database]
host = "localhost"
port = 5432
timeout = 30.5
[features]
enabled = ["auth", "logging", "metrics"]Parse it with mojo-toml:
from toml import parse
fn main() raises:
# Read TOML file
var content: String
with open("examples/quickstart.toml", "r") as f:
content = f.read()
# Parse and access values
var config = parse(content)
# Access nested tables
var app = config["app"].as_table()
print("App:", app["name"].as_string())
print("Version:", app["version"].as_string())
var db = config["database"].as_table()
print("Database:", db["host"].as_string(), ":", db["port"].as_int())
print("Timeout:", db["timeout"].as_float())
# Access arrays
var features = config["features"].as_table()["enabled"].as_array()
print("Features enabled:", len(features))Create configuration programmatically and write to TOML:
from toml import to_toml, TomlValue
fn main() raises:
# Build configuration using Dict and TomlValue
var config = Dict[String, TomlValue]()
# Create app section
var app = Dict[String, TomlValue]()
app["name"] = TomlValue("QuickStart")
app["version"] = TomlValue("2.0.0")
app["debug"] = TomlValue(True)
config["app"] = TomlValue(app^)
# Create database section
var db = Dict[String, TomlValue]()
db["host"] = TomlValue("localhost")
db["port"] = TomlValue(5432)
db["timeout"] = TomlValue(30.5)
config["database"] = TomlValue(db^)
# Create features array
var enabled = List[TomlValue]()
enabled.append(TomlValue("auth"))
enabled.append(TomlValue("logging"))
enabled.append(TomlValue("metrics"))
var features = Dict[String, TomlValue]()
features["enabled"] = TomlValue(enabled^)
config["features"] = TomlValue(features^)
# Convert to TOML and write to file
var toml_str = to_toml(config)
with open("output.toml", "w") as f:
f.write(toml_str)
print("Configuration written to output.toml")Note for Python users: Unlike Python's tomli where you access values directly (config["app"]["name"]), mojo-toml requires explicit type conversions (.as_table(), .as_string(), etc.) because Mojo is statically typed. This provides type safety and clear error messages at the cost of slightly more verbose code.
Try it yourself: This example is available as examples/quickstart.mojo. Run it with:
pixi run example-quickstartWe're tracking Mojo's reflection capabilities for automatic struct serialisation:
// Future API (v0.8.0+)
struct Config:
var name: String
var port: Int
var debug: Bool
var config = from_toml[Config]("config.toml") // No .as_*() needed!
print(config.name) // Direct field accessThis will eliminate all the .as_string(), .as_int() boilerplate. Blocked on runtime field access in Mojo's reflection module. See REFLECTION_SERIALIZATION.md for details.
Choose the installation method that best fits your workflow:
Best for version-controlled projects with easy updates.
# Add to your project
cd your-project
git submodule add https://github.com/databooth/mojo-toml vendor/mojo-toml
# Use in your code
mojo -I vendor/mojo-toml/src your_app.mojo
# Update to latest version
git submodule update --remote vendor/mojo-tomlSimplest method for quick projects.
# Clone and copy source
git clone https://github.com/databooth/mojo-toml
cp -r mojo-toml/src/toml your-project/lib/toml
# Use in your code
mojo -I your-project/lib your_app.mojo# Future installation method via modular-community channel
pixi add mojo-tomlmojo-toml implements the complete TOML 1.0 specification (https://toml.io/en/v1.0.0):
- Basic types: strings, integers, floats, booleans
- Strings: basic, literal, multiline (both basic and literal)
- Numbers: integers, floats, underscores, special values (inf, nan)
- Alternative number bases: hex (
0xDEAD), octal (0o755), binary (0b1101) โจ v0.5.0 - Arrays:
[1, 2, 3]with nesting and mixed types - Inline tables:
{name = "value"}with nesting - Table headers:
[section]with proper nesting - Array of tables:
[[section]]for repeated table arrays โจ v0.5.0 - Dotted keys:
a.b.c = "value"creating nested structures - Duplicate detection: validates and rejects duplicate keys
- Error messages: precise line and column context
- TOML writer: serialize
Dict[String, TomlValue]to TOML format - Round-trip support: parse โ modify โ write โ parse preserves semantic equality
Date/Time values: Parsed and validated according to TOML 1.0, returned as ISO 8601 strings. Native Mojo datetime objects are not yet used due to ongoing standard library development. This does not affect TOML parsing correctness or round-trip fidelity.
TOML 1.1 features implemented:
- โ
\\xHHescape sequences for codepoints 0-255 (e.g.,\\x00,\\x61) - โ
\\eescape for escape character (U+001B)
TOML 1.1 features not yet implemented:
- Multiline inline tables with trailing commas
- Optional seconds in datetime/time values
See ROADMAP.md for development timeline.
- Mojo 2025/2026 (via pixi)
- Python 3.10+ (for validation tests)
# Clone repository
git clone https://github.com/databooth/mojo-toml
cd mojo-toml
# Install dependencies
pixi install
# Run tests
pixi run test-all
# Run examples
pixi run example-simple
pixi run example-piximojo-toml/
โโโ src/toml/ # Source code
โ โโโ __init__.mojo # Public API: parse(), to_toml()
โ โโโ lexer.mojo # Tokenisation
โ โโโ parser.mojo # TOML parsing
โ โโโ writer.mojo # TOML serialisation
โโโ tests/ # Test suite (168 tests)
โโโ examples/ # Usage examples
โโโ benchmarks/ # Performance benchmarks
โโโ fixtures/ # Test TOML files
โโโ docs/ # Documentation
โ โโโ PERFORMANCE.md # Performance characteristics
โ โโโ planning/ # Planning and historical docs
โโโ packaging/ # Conda packaging files
Run performance benchmarks with full system reporting:
# Mojo benchmark (mojo-toml performance)
pixi run benchmark-mojo
# Python baseline (tomllib/tomli_w comparison)
pixi run benchmark-pythonBoth benchmarks generate markdown reports in benchmarks/reports/ with:
- System specifications (OS, CPU, GPU, RAM, Mojo/Python versions)
- Performance tables with throughput and latency
- Timestamp and machine configuration
See PERFORMANCE.md for detailed results and analysis.
- PERFORMANCE.md - Performance benchmarks and characteristics
- CHANGELOG.md - Version history and changes
- docs/planning/ - Development roadmap, design docs, and project history
Contributions welcome! This project is open source (MIT License).
How to contribute:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run
pixi run test-allto ensure tests pass - Submit a pull request
See ROADMAP.md for areas where contributions would be most valuable.
Other Mojo Config Libraries:
- mojo-ini - INI file parser with Python configparser compatibility
- mojo-dotenv - Load environment variables from .env files
Other TOML Parsers in Mojo:
- decimojo/tomlmojo - Lightweight TOML parser (~900 LOC, parser-only) embedded in the decimojo library. Good choice if you only need basic config reading for tests and don't need a standalone package or TOML 1.0 features.
Special thanks to:
- DataBooth - Project sponsor, building high-performance data and AI services with Mojo
- Python tomli - Reference implementation for validation
- TOML Specification - Tom Preston-Werner's excellent config format
- Modular Team - For creating the Mojo programming language
MIT License - See LICENSE for details.