JSON vs YAML vs TOML vs XML: Picking a Format for Config and Data
Most developers work with all four of these formats every week, usually without choosing any of them: package.json, a Kubernetes manifest in YAML, Cargo.toml or pyproject.toml, and an XML response from some older enterprise API. When you do get to choose, the differences matter more than they first appear.
Here is the same small configuration in each format, followed by where each one is strong and where it will surprise you.
The same config, four ways
JSON
{
"service": "billing",
"port": 8080,
"debug": false,
"allowed_countries": ["IN", "NO", "US"],
"database": { "host": "db.internal", "pool_size": 10 }
}
YAML
# Billing service config
service: billing
port: 8080
debug: false
allowed_countries: [IN, NO, US]
database:
host: db.internal
pool_size: 10
TOML
# Billing service config
service = "billing"
port = 8080
debug = false
allowed_countries = ["IN", "NO", "US"]
[database]
host = "db.internal"
pool_size = 10
XML
<!-- Billing service config -->
<config>
<service>billing</service>
<port>8080</port>
<debug>false</debug>
<allowed_countries>
<country>IN</country><country>NO</country><country>US</country>
</allowed_countries>
<database host="db.internal" pool_size="10"/>
</config>
Look closely at the YAML version: it contains a bug. We'll come back to it.
JSON
Strengths: a tiny, unambiguous grammar; a parser in the standard library of practically every language; and native in JavaScript. For data exchange between programs, such as API payloads and message queues, it's the default for good reason.
Weaknesses for config: no comments, no trailing commas, and mandatory quoting make it tedious to hand-edit — which is exactly why JSONC and JSON5 exist. Numbers are also a subtle trap. JSON itself places no limit on precision, but many parsers, including JavaScript's, read numbers as 64-bit floats. Integers above 253 − 1, such as some database IDs and snowflake IDs, silently lose precision. Send those as strings.
YAML
Strengths: the most readable of the four for nested configuration, with comments, and support for anchors (&/*) that let you reuse blocks. It dominates infrastructure tooling: Kubernetes, Docker Compose, GitHub Actions, Ansible.
Weaknesses: the specification is large, and its implicit typing surprises people. Now for the bug in our example.
The "Norway problem"
In YAML 1.1, which is still what many popular parsers implement, including PyYAML, unquoted yes, no, on, off, y, and n are booleans. So:
allowed_countries: [IN, NO, US]
parses as ["IN", false, "US"]. Norway's country code became false. YAML 1.2 (2009) restricted booleans to true and false, but parser support varies. Other implicit-typing traps:
- Version numbers:
version: 1.10becomes the float1.1. - Leading zeros: some YAML 1.1 parsers read
0755as octal (493), which is useful for file modes but surprising for ZIP codes. - Sexagesimal numbers: in YAML 1.1,
22:22can parse as the integer 1342, a base-60 number, which famously broke port mappings.
The fix is simple: quote any string that could possibly be read as something else. Many teams quote all string values in YAML for exactly this reason.
Indentation is also significant, and tabs are not allowed for it. A single mis-indented line can move a key into a different parent object without any parse error.
TOML
Strengths: designed specifically for configuration files. It has comments, explicit types (strings are always quoted, so there's no Norway problem), native date-time values, and no significant indentation. It's the standard for Rust (Cargo.toml) and modern Python packaging (pyproject.toml).
Weaknesses: deeply nested structures get awkward. Each level needs a [section.subsection] header, and arrays of tables use the less intuitive [[double-bracket]] syntax. It's excellent for flat-to-moderately-nested config, and a poor fit for arbitrary data exchange.
XML
Strengths: mature schema validation (XSD), namespaces for mixing vocabularies, a clear distinction between attributes and element content, and powerful query and transformation tools (XPath, XSLT). It's still the format behind SOAP, many enterprise and financial integrations, office document formats, SVG, and Android layouts.
Weaknesses: verbose, and it doesn't map cleanly onto the objects and arrays most languages use. Converting XML to JSON forces decisions: does an attribute become a key? Is a single <country> element an array of one or a plain value? Different converters answer differently. Parsers must also be configured safely — disable external entity resolution to avoid XXE attacks when processing untrusted XML.
Comparison table
| JSON | YAML | TOML | XML | |
|---|---|---|---|---|
| Comments | No | Yes | Yes | Yes |
| Hand-editing | Tedious | Pleasant | Pleasant | Verbose |
| Type surprises | Large integers | Many | Few | Everything is text |
| Deep nesting | Good | Good | Awkward | Good |
| Schema validation | JSON Schema | JSON Schema (via conversion) | Limited | XSD |
| Best at | Data exchange | Infra config | App config | Documents, legacy integrations |
Recommendations
- API payloads and machine-to-machine data: JSON.
- Application config that humans edit: TOML if the structure is shallow; YAML if it's deeply nested — with quoted strings.
- You're inside an ecosystem with a convention, such as Kubernetes YAML or Rust TOML: follow the convention. Consistency beats marginal technical merit.
- You're integrating with an existing XML system: keep XML at that boundary and convert to your internal format just inside it.
Converting between formats safely
Conversion is where subtle data loss happens. Before you trust a converted file:
- Check types, not just text. Did a YAML
nobecomefalse? Did a large ID lose digits? - Check comments. JSON can't hold them, so a YAML → JSON → YAML round trip deletes them all.
- Check XML structure decisions: attributes versus elements, and single-element arrays.
- Diff structurally. Compare the parsed documents rather than the text. A text diff of two formats is meaningless, but a structural diff of the parsed results shows exactly which values changed.
If JSON is your chosen format, our guides on common JSON syntax errors and JSON Schema are good next reads.