Free & open source — no account required
Free & open source — no account required
This technical guide provides an in-depth analysis of the json to toml engine, best practices for implementation, and data security standards.
TOML is the configuration format of choice for Rust (Cargo.toml), Python (pyproject.toml), and an increasing number of developer tools. Converting JSON to TOML isn't just reformatting — TOML has native date/time types JSON lacks, a two-tier nesting model (tables and array of tables), and rules about key ordering that affect output clarity. The critical TOML concept JSON developers miss is the array of tables ([[section]]): the only way to represent an array of objects in TOML, used for dependencies, plugins, and multi-server configuration.
import TOML from '@iarna/toml';
// Input JSON config
const config = {
package: {
name: "myapp",
version: "1.2.0",
description: "A demo application",
authors: ["Alice Chen ", "Bob Kim "],
repository: "https://github.com/example/myapp",
license: "MIT",
edition: "2024",
},
dependencies: {
"serde": { version: "1.0", features: ["derive"] },
"tokio": { version: "1", features: ["full"] },
"reqwest": { version: "0.11", optional: true },
},
dev_dependencies: {
"criterion": "0.5",
"proptest": "1.0",
},
profile: {
release: { opt_level: 3, lto: "thin", codegen_units: 1 },
dev: { opt_level: 0, debug: true },
},
};
const tomlString = TOML.stringify(config);
console.log(tomlString);
// Output:
// [package]
// name = "myapp"
// version = "1.2.0"
// description = "A demo application"
// authors = ["Alice Chen ", "Bob Kim "]
// repository = "https://github.com/example/myapp"
// license = "MIT"
// edition = "2024"
//
// [dependencies.serde]
// version = "1.0"
// features = ["derive"]
//
// [dependencies.tokio]
// version = "1"
// features = ["full"]
//
// [dependencies.reqwest]
// version = "0.11"
// optional = true
//
// [dev_dependencies]
// criterion = "0.5"
// proptest = "1.0"
//
// [profile.release]
// opt_level = 3
// lto = "thin"
// codegen_units = 1
//
// [profile.dev]
// opt_level = 0
// debug = true
// Parsing TOML back to JavaScript object
const parsed = TOML.parse(tomlString);
console.log(parsed.package.version); // "1.2.0"
console.log(parsed.dependencies.tokio); // { version: "1", features: ["full"] }
// TOML's array of tables ([[section]]) represents an array of objects
// This is NOT the same as a TOML array of simple values
// JSON input with array of objects:
const serverConfig = {
servers: [
{ host: "web-01.internal", port: 8080, role: "primary", region: "us-east" },
{ host: "web-02.internal", port: 8080, role: "replica", region: "us-east" },
{ host: "web-03.internal", port: 8081, role: "replica", region: "eu-west" },
],
databases: [
{ url: "postgres://db1.internal/app", pool_min: 5, pool_max: 20 },
{ url: "postgres://db2.internal/audit", pool_min: 2, pool_max: 5 },
],
};
// @iarna/toml correctly generates array of tables:
TOML.stringify(serverConfig);
// [[servers]]
// host = "web-01.internal"
// port = 8080
// role = "primary"
// region = "us-east"
//
// [[servers]]
// host = "web-02.internal"
// port = 8080
// role = "replica"
// region = "us-east"
//
// [[servers]]
// host = "web-03.internal"
// port = 8081
// role = "replica"
// region = "eu-west"
//
// [[databases]]
// url = "postgres://db1.internal/app"
// pool_min = 5
// pool_max = 20
//
// [[databases]]
// url = "postgres://db2.internal/audit"
// pool_min = 2
// pool_max = 5
// Parsing array of tables — result is a JS array of objects
const parsed = TOML.parse(tomlOutput);
parsed.servers.forEach(s => console.log(s.host, s.region));
// TOML has four native date/time types that JSON lacks:
// 1. Offset Date-Time: 2024-03-15T10:30:00Z
// 2. Local Date-Time: 2024-03-15T10:30:00 (no timezone)
// 3. Local Date: 2024-03-15
// 4. Local Time: 10:30:00
// In @iarna/toml, JavaScript Date objects serialize to TOML Offset Date-Time
const release = {
released_at: new Date('2024-03-15T10:00:00Z'), // JS Date → TOML datetime
maintenance_until: new Date('2025-03-15'),
};
TOML.stringify(release);
// released_at = 2024-03-15T10:00:00.000Z
// maintenance_until = 2025-03-15T00:00:00.000Z
// TOML Local Date (no time) — use TOML.LocalDate from @iarna/toml
import { LocalDate, LocalTime, LocalDateTime } from '@iarna/toml';
const config = {
start_date: new LocalDate(2024, 3, 15), // 2024-03-15
daily_reset: new LocalTime(0, 0, 0), // 00:00:00
published: new LocalDateTime(2024, 3, 15, 10, 0), // 2024-03-15T10:00:00
};
TOML.stringify(config);
// start_date = 2024-03-15
// daily_reset = 00:00:00
// published = 2024-03-15T10:00:00
// Python's pyproject.toml uses TOML for all project configuration
// Generate it from a JSON project definition:
const pythonProject = {
tool: {
poetry: {
name: "data-pipeline",
version: "0.3.1",
description: "ETL pipeline for analytics",
authors: ["Data Team "],
packages: [{ include: "pipeline" }],
dependencies: {
python: "^3.11",
pandas: "^2.0.0",
"pydantic": "^2.0.0",
httpx: { version: "^0.25.0", extras: ["http2"] },
},
},
ruff: {
line_length: 100,
target_version: ["py311"],
select: ["E", "F", "I", "N", "W"],
ignore: ["E501"],
"per-file-ignores": { "tests/**": ["S101"] },
},
mypy: {
python_version: "3.11",
strict: true,
ignore_missing_imports: false,
},
pytest: {
ini_options: {
testpaths: ["tests"],
asyncio_mode: "auto",
addopts: "--cov=pipeline --cov-report=term-missing",
},
},
},
build_system: {
requires: ["poetry-core>=1.0.0"],
"build-backend": "poetry.core.masonry.api",
},
};
const pyprojectToml = TOML.stringify(pythonProject);
writeFileSync('pyproject.toml', pyprojectToml);
// Generates:
// [tool.poetry]
// name = "data-pipeline"
// ...
// [tool.ruff]
// ...
// [build-system]
// ...
[table] or [[array of tables]] headers. Violating this order causes a parse error. When generating TOML programmatically, ensure scalar values at the root are output before nested tables.[dependencies.serde] is equivalent to [dependencies] followed by [dependencies.serde]. For sparse objects (most keys are undefined), the dotted syntax is cleaner. For dense objects (all keys defined), a [section] block is cleaner. @iarna/toml uses dotted keys for inline-friendly shapes automatically."release_date": "2024-03-15", convert it to a TOML LocalDate when generating TOML. Tools that read TOML (Cargo, Poetry, rustfmt) understand native date types and can validate ranges, compare versions, and compute durations without string parsing.Q: Why doesn't TOML support null/nil?
A: By design — TOML is for configuration, not data transfer. A configuration key with no value should either be omitted or use a sentinel value ("", -1, false). If you need null semantics in a TOML-configured application, handle it at the application layer by checking for the absence of the key rather than a null value. This is one reason TOML is not used for JSON-equivalent data exchange.
Q: Can TOML files import other TOML files?
A: TOML has no include or import directive — there's no equivalent of YAML's !!include. If your configuration is complex enough to need includes, it's usually a sign that you should use a proper configuration management system (like Ansible group_vars or Kubernetes ConfigMaps) rather than TOML files. Some tools (like Cargo workspaces) handle multi-file configuration at the tool level, not the TOML spec level.
Q: Does @iarna/toml support TOML 1.0?
A: Yes, @iarna/toml v3.0+ is TOML 1.0 compliant. The older toml npm package (without the @iarna scope) supports an older spec version. For full TOML 1.0 support including the 8-byte hex escape (\UHHHHHHHH), use @iarna/toml or the newer smol-toml package which is TOML 1.0 compliant and has no dependencies.
Is the processing local-only?
Absolutely. TypeMorph operates entirely within your browser's sandbox. We use Web Workers for high-performance computation without ever transmitting your JSON, SQL, or API data to a remote server.
Can I use this for enterprise projects?
Yes. The tool is designed for professional software engineers who require GDPR compliance and data privacy. It is trusted by developers at top-tier startups and financial institutions.