When setting up a new project, you'll often face a choice: JSON or YAML for configuration? Both formats can represent the same data, but they have different strengths. Let's compare them.
JSON and YAML Origins
JSON (JavaScript Object Notation) emerged in the early 2000s as a lightweight alternative to XML. It's a subset of JavaScript and prioritizes simplicity and machine-readability.
YAML (YAML Ain't Markup Language) was created in 2001 with a focus on human readability. It's a superset of JSON—meaning any valid JSON is also valid YAML.
Syntax Comparison
The same data in both formats:
JSON:
{
"server": {
"host": "localhost",
"port": 8080,
"ssl": true
},
"database": {
"connection": "postgres://localhost:5432/mydb",
"pool_size": 10
},
"allowed_origins": [
"https://example.com",
"https://api.example.com"
]
}
YAML:
server:
host: localhost
port: 8080
ssl: true
database:
connection: postgres://localhost:5432/mydb
pool_size: 10
allowed_origins:
- https://example.com
- https://api.example.com
Key differences:
- YAML uses indentation instead of braces
- YAML doesn't require quotes around most strings
- YAML uses
:for key-value pairs (no quotes on keys) - YAML arrays use
-instead of[brackets]
Readability Differences
YAML is generally more readable for humans:
Nested structure in JSON:
{
"logging": {
"level": "info",
"format": "json",
"outputs": [
{"type": "console"},
{"type": "file", "path": "/var/log/app.log"}
]
}
}
Same in YAML:
logging:
level: info
format: json
outputs:
- type: console
- type: file
path: /var/log/app.log
The YAML version has less visual noise—no quotes, braces, or commas cluttering the view.
Comments: YAML Yes, JSON No
One of YAML's biggest advantages:
# Database configuration
database:
host: localhost # Use 'db' in production
port: 5432
# pool_size: 10 # Uncomment for production
JSON has no comment syntax. People work around this with:
{
"_comment": "Database configuration",
"database": {
"host": "localhost"
}
}
But these fake comments become part of the data and may cause issues.
When to Use JSON
Choose JSON when:
1. Working with APIs
APIs universally use JSON. It's the standard:
{"status": "success", "data": {"id": 123}}
2. Programmatic generation
JSON is easier to generate from code:
const config = JSON.stringify(settings, null, 2);
3. Strict validation needed
JSON's strictness catches errors early—no ambiguity.
4. Cross-platform data exchange
Every language has robust JSON support.
5. Browser environments
JavaScript natively parses JSON with JSON.parse().
When to Use YAML
Choose YAML when:
1. Human-edited configuration
YAML's readability shines for config files:
# Application settings
app:
name: My App
debug: true
features:
- authentication
- notifications
2. DevOps and infrastructure
Kubernetes, Docker Compose, Ansible, and many CI/CD tools use YAML:
# docker-compose.yml
services:
web:
image: nginx
ports:
- "80:80"
3. Documentation is needed
Comments let you explain configuration inline:
timeout: 30 # seconds, increase for slow networks
4. Multi-document files
YAML supports multiple documents in one file:
---
# Development config
environment: development
debug: true
---
# Production config
environment: production
debug: false
YAML Gotchas: The Norway Problem
YAML's flexibility creates surprising behaviors:
Boolean coercion
YAML interprets certain words as booleans:
country: Norway # String ✓
country: NO # Boolean false! ✗
The two-letter country code for Norway (NO) becomes false. Same with:
yes,no→true,falseon,off→true,falsey,n→true,false
Fix: Quote ambiguous strings:
country: "NO"
Number coercion
version: 1.0 # Number 1 (not "1.0")
version: "1.0" # String "1.0" ✓
zipcode: 01234 # Octal number! (668 in decimal)
zipcode: "01234" # String ✓
Colons in strings
title: Hello: World # Parse error!
title: "Hello: World" # OK ✓
Multi-line strings
YAML has multiple ways to handle multi-line strings:
# Literal block (preserves newlines)
description: |
Line 1
Line 2
# Folded block (joins lines)
description: >
This is a long
description that
becomes one line.
Converting Between Formats
YAML to JSON
Python:
import yaml
import json
with open('config.yaml') as f:
data = yaml.safe_load(f)
print(json.dumps(data, indent=2))
Command line (with yq):
yq -o=json config.yaml
JSON to YAML
Python:
import yaml
import json
with open('config.json') as f:
data = json.load(f)
print(yaml.dump(data, default_flow_style=False))
Best Practices for Config Files
JSON config files
{
"server": {
"host": "0.0.0.0",
"port": 3000
}
}
- Always pretty-print for readability
- Use a JSON schema for validation
- Consider JSON5 or JSONC for comments
YAML config files
# Application configuration
# See docs/configuration.md for details
server:
host: "0.0.0.0" # Quote strings that could be ambiguous
port: 3000
# Timeout values in seconds
timeouts:
connect: 5
read: 30
- Quote strings that might be misinterpreted
- Use comments to explain non-obvious settings
- Be consistent with indentation (2 spaces is common)
- Validate with a schema (like JSON Schema, which works for YAML too)
Feature Comparison
| Feature | JSON | YAML | XML |
|---|---|---|---|
| Human readable | Good | Better | Fair (verbose) |
| Machine readable | Excellent | Good | Good |
| Comments | No | Yes | Yes |
| Multi-document files | No | Yes | No (one root element) |
| Strict syntax | Yes | No (more flexible) | Yes (must be well-formed) |
| Native data types | Yes | Yes | No (everything is text unless a schema types it) |
| Attributes vs elements | No | No | Yes (two ways to store a value) |
| Schema validation | JSON Schema | JSON Schema (via tools) | XSD, DTD, RELAX NG |
| Namespaces | No | No | Yes |
| Mixed content (text with inline markup) | No | No | Yes |
| Learning curve | Low | Medium | Medium to high |
| Error messages | Clear | Sometimes cryptic | Clear |
| Whitespace significant | No | Yes | No |
| Native browser support | Yes (JSON.parse) |
No | Yes (DOMParser) |
| Typical size | Compact | Compact | Largest |
What about XML?
XML (eXtensible Markup Language) predates both formats and is still everywhere, so it is worth seeing the same configuration a third way:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<server host="localhost" port="8080" ssl="true" />
<database>
<connection>postgres://localhost:5432/mydb</connection>
<poolSize>10</poolSize>
</database>
<allowedOrigins>
<origin>https://example.com</origin>
<origin>https://api.example.com</origin>
</allowedOrigins>
</config>
Verbosity. Every element needs an opening and a closing tag, so the XML version is noticeably longer than the JSON and far longer than the YAML for the same data. That costs bytes on the wire and effort when editing by hand.
Attributes versus elements. XML has two ways to attach a value: as an attribute (<server host="localhost">) or as a child element (<server><host>localhost</host></server>). JSON and YAML have exactly one. The choice is a matter of style, but it means there is no single correct mapping between XML and JSON, which is why converters have to adopt a convention such as prefixing attribute names with @. Our XML to JSON converter handles that mapping in both directions.
Everything is text. port="8080" is a string until a schema says otherwise. JSON and YAML distinguish numbers, booleans and null natively.
Schemas and tooling. This is where XML is strongest. XML Schema (XSD), DTDs, XPath for querying, XSLT for transformation, namespaces for mixing vocabularies, and XML digital signatures are all mature, standardised and supported in every major platform. JSON Schema is widely used but younger, and YAML normally borrows it.
Comments. XML supports <!-- comments -->, like YAML and unlike JSON.
Where XML still wins:
- Document markup. Text with inline structure such as
<p>Hello <b>world</b></p>is natural in XML and awkward in JSON or YAML. HTML, SVG, DocBook and the internals of DOCX and XLSX files are all XML. - SOAP and enterprise integration. SOAP web services, WSDL, and the WS-* standards are XML-based and still common in banking, insurance, government and older B2B integrations.
- Configuration in the Java and .NET worlds. Maven's
pom.xml, Android manifests and layouts, Spring XML configuration, .NET'sweb.config,.csprojand MSBuild files, and NuGet.nuspecfiles are all XML. - Established formats. RSS and Atom feeds, XML sitemaps, and many industry data standards are defined as XML and are not changing.
Where it loses: REST APIs (JSON won that decisively), human-edited configuration (YAML is easier to read and write), and browser-side code, where JSON.parse is one line and XML needs DOM traversal. To tidy an XML document you are working with, use the XML Formatter.
Which should I use?
| Situation | Choose |
|---|---|
| REST or GraphQL API, browser code, general data interchange | JSON |
| Human-edited configuration; Kubernetes, Docker Compose, GitHub Actions, Ansible | YAML |
| Document markup, SOAP or enterprise integration, Java/.NET build and app config, SVG, RSS, sitemaps | XML |
| Configuration that needs comments | YAML or XML (or JSONC/JSON5 if your tools accept it) |
| Strict validation against a schema | XML with XSD, or JSON with JSON Schema |
| Several documents in one file | YAML |
| Smallest payload and fastest parsing | JSON |
Summary
- JSON: use for APIs, data exchange, browser code, and when you need strict, predictable parsing.
- YAML: use for human-edited configuration, DevOps tooling, and when you need comments or multiple documents in one file. Quote anything that could be misread as a boolean, number or date.
- XML: use for document markup, SOAP and enterprise integrations, Java and .NET configuration, and formats that are defined as XML. Accept the verbosity in exchange for mature schemas and tooling.
None of the three is universally "better". Many projects use all of them: YAML for configuration, JSON for API responses, and XML for the build system or a legacy integration.
Need to convert between formats? Try our JSON to YAML Converter and XML to JSON Converter, and tidy up with the JSON Formatter or XML Formatter.