JSON (JavaScript Object Notation) and YAML (YAML Ain't Markup Language) are two of the most widely used data serialization formats in modern software development. Both serve the same fundamental purpose -- representing structured data as text -- but they take very different approaches to syntax, readability, and feature sets. Understanding both formats and knowing how to convert between them is an essential skill for any developer working with APIs, configuration files, infrastructure-as-code, or cloud-native platforms.
JSON emerged from the JavaScript ecosystem in the early 2000s, popularized by Douglas Crockford as a lightweight alternative to XML for data interchange. Its syntax is derived directly from JavaScript object literal notation, making it instantly familiar to web developers. JSON quickly became the dominant format for REST APIs, browser-server communication, and NoSQL databases.
JSON's design philosophy prioritizes simplicity and unambiguity. It supports exactly six data types: strings (in double quotes), numbers, booleans (true/false), null, arrays (ordered lists), and objects (key-value maps). There are no comments, no special types, and no optional syntax variations. This strictness is both its greatest strength -- any conforming JSON parser will interpret any valid JSON document identically -- and its limitation for use cases where human readability and authoring ergonomics matter.
JSON is formally specified by RFC 8259 and ECMA-404. Every modern programming language includes built-in or standard-library JSON support, making it the most universally portable data format in existence.
YAML was originally introduced in 2001 by Clark Evans, Ingy dot Net, and Oren Ben-Kiki. The name originally stood for "Yet Another Markup Language" but was later reinterpreted as the recursive acronym "YAML Ain't Markup Language," reflecting its shift in focus from document markup to data serialization.
YAML's design philosophy prioritizes human readability. It uses whitespace indentation instead of braces and brackets to denote structure, eliminates most quotation marks, and supports features specifically designed for human authors: comments, multi-line strings, anchors and aliases for reusing data, and the ability to include multiple documents in a single file. These features make YAML the format of choice for configuration files where humans are the primary readers and writers.
YAML's popularity exploded with the rise of DevOps and cloud-native computing. Today, it is the standard configuration format for Kubernetes, Docker Compose, Ansible, GitHub Actions, GitLab CI, Terraform (in HCL-to-YAML workflows), Helm charts, and countless other tools in the infrastructure-as-code ecosystem.
The current specification is YAML 1.2.2, released in 2021. A critical change in YAML 1.2 was making YAML a strict superset of JSON, meaning any valid JSON document is also a valid YAML document.
The best way to understand the differences between JSON and YAML is to see the same data represented in both formats. Here is a Kubernetes Deployment manifest expressed in each format.
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "web-server",
"namespace": "production",
"labels": {
"app": "web-server",
"version": "v2.1.0"
}
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "web-server"
}
},
"template": {
"metadata": {
"labels": {
"app": "web-server",
"version": "v2.1.0"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.25-alpine",
"ports": [
{
"containerPort": 80
}
],
"resources": {
"requests": {
"cpu": "100m",
"memory": "128Mi"
},
"limits": {
"cpu": "500m",
"memory": "256Mi"
}
}
}
]
}
}
}
}
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: production
labels:
app: web-server
version: v2.1.0
spec:
replicas: 3
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
version: v2.1.0
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
| Feature | JSON | YAML |
|---|---|---|
| Structure delimiters | { } and [ ] | Indentation (spaces) |
| String quoting | Always required (double quotes) | Optional in most cases |
| Comments | Not supported | Supported (#) |
| Multi-line strings | Escape sequences (\n) | | (literal) and > (folded) |
| Multiple documents | Not supported | --- separator |
| Anchors/Aliases | Not supported | &anchor / *alias |
| Data types | 6 types | 6+ types (dates, binary, etc.) |
| Trailing commas | Not allowed | N/A (no commas) |
| File extensions | .json | .yaml or .yml |
| MIME type | application/json | application/yaml |
Converting between JSON and YAML is a straightforward mapping because both formats express the same underlying data model: scalars (strings, numbers, booleans, null), sequences (ordered lists), and mappings (key-value pairs). Here is how each JSON construct maps to its YAML equivalent.
JSON objects enclosed in { } become YAML mappings with each key-value pair on its own line. The braces are removed, and key-value pairs are represented as key: value with the colon and space serving as the delimiter.
// JSON
{"name": "nginx", "version": "1.25"}
# YAML
name: nginx
version: "1.25"
JSON arrays enclosed in [ ] become YAML sequences where each element is prefixed with a dash (-) on its own line. Nested arrays and objects within arrays follow the same indentation rules.
// JSON
["alpha", "beta", "gamma"]
# YAML
- alpha
- beta
- gamma
JSON requires all strings to be enclosed in double quotes. YAML is more flexible -- most strings can be written unquoted, but quoting is required when a string contains special characters, starts with a reserved indicator, or could be misinterpreted as another data type:
hello, web-server, nginx:, #, {, [, &, *, !, |, >, ', ", %, @, or leading/trailing spacesyes, no, true, false), numbers (3.14, 42), or null (null, ~) when you want them treated as strings
These scalar types map directly between formats. JSON true becomes YAML true, JSON null becomes YAML null (or ~), and numbers remain unchanged. The key difference is that YAML also treats unquoted yes, no, on, off as booleans (in YAML 1.1), which is a frequent source of bugs.
Nested JSON objects and arrays are represented in YAML through increased indentation. Each level of nesting adds a consistent number of spaces (typically 2). This is where YAML's readability advantage is most apparent -- deeply nested structures that require matching braces in JSON are expressed through clean, visual indentation in YAML.
// JSON
{
"database": {
"primary": {
"host": "db-primary.example.com",
"port": 5432,
"credentials": {
"username": "admin",
"password": "secret"
}
}
}
}
# YAML
database:
primary:
host: db-primary.example.com
port: 5432
credentials:
username: admin
password: secret
Since YAML 1.2, YAML is officially a strict superset of JSON. This means that any valid JSON document can be parsed by a YAML parser and will produce identical data structures. This is a deliberate design decision that makes migration between formats seamless and allows YAML tooling to handle JSON input natively.
This superset relationship has practical implications. You can paste JSON directly into a YAML file and it will parse correctly. You can mix JSON-style inline syntax with YAML block syntax in the same document. And you can incrementally convert a JSON configuration to YAML by replacing JSON constructs with their YAML equivalents one section at a time.
However, the reverse is not true. YAML has features that JSON cannot represent:
# inline comments that are discarded during parsing. JSON has no comment syntax at all.&anchor) and reference it elsewhere (*alias), avoiding repetition. JSON requires duplicating data.|) and folded block scalar (>) handle multi-line text elegantly. JSON must use \n escape sequences within a single string.!!timestamp, !!binary) for representing dates, binary data, and custom types. JSON has no type annotation mechanism.---. JSON files contain exactly one value.When converting from YAML to JSON, these YAML-specific features are either lost (comments), expanded (anchors/aliases become duplicated data), or transformed (multi-line strings become escaped strings). The data values are preserved, but the authoring conveniences are not.
Kubernetes is perhaps the most prominent system where the choice between JSON and YAML matters on a daily basis. While the Kubernetes API server accepts both formats, YAML has become the de facto standard for writing and maintaining Kubernetes manifests. Understanding why -- and knowing when JSON is the better choice -- is important for effective Kubernetes operations.
Several YAML features make it particularly well-suited for Kubernetes manifests:
--- separator allows you to define multiple related resources (a Deployment, Service, and ConfigMap) in a single file, keeping related resources together.| or > block scalars.Despite YAML's dominance in human-authored manifests, JSON has legitimate Kubernetes use cases:
kubectl get with -o json outputs JSON, and many tools that interact with the Kubernetes API work with JSON natively.Kubernetes makes format conversion easy. You can output any resource in either format:
# Get a deployment as JSON
kubectl get deployment web-server -o json
# Get the same deployment as YAML
kubectl get deployment web-server -o yaml
# Apply a JSON file (works the same as YAML)
kubectl apply -f deployment.json
# Convert YAML to JSON using kubectl
kubectl create -f deployment.yaml --dry-run=client -o json
One of YAML's most powerful features for Kubernetes is the ability to define multiple resources in a single file. This is commonly used to keep related resources together:
apiVersion: v1
kind: Namespace
metadata:
name: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:latest
---
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: my-app
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
This pattern has no JSON equivalent. If you convert this to JSON, you would need three separate files or a custom wrapper format (like a JSON array of documents).
CI/CD platforms have overwhelmingly adopted YAML as their configuration format. Understanding YAML's role in CI/CD pipelines and knowing when JSON conversion is needed are critical skills for modern DevOps workflows.
GitHub Actions workflow files are written exclusively in YAML. The format's features align perfectly with workflow definitions:
name: Build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm test
- run: npm run build
GitLab CI/CD configuration uses .gitlab-ci.yml, which takes advantage of YAML anchors and aliases to reduce repetition across pipeline stages:
.default_rules: &default_rules
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_MERGE_REQUEST_ID
build:
stage: build
<<: *default_rules
script:
- npm ci
- npm run build
test:
stage: test
<<: *default_rules
script:
- npm ci
- npm test
The anchor &default_rules defines the rules once, and *default_rules with the merge key << reuses them in multiple jobs. This kind of DRY (Don't Repeat Yourself) pattern is impossible in JSON.
Docker Compose files use YAML to define multi-container applications. Comments are particularly valuable here for documenting port mappings, environment variables, and volume mounts:
services:
web:
image: nginx:alpine
ports:
- "8080:80" # Map host 8080 to container 80
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- api
api:
build: ./api
environment:
- DATABASE_URL=postgres://db:5432/myapp
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: secret # Use secrets in production
cache:
image: redis:7-alpine
volumes:
pgdata:
Although CI/CD configurations are written in YAML, there are situations where JSON conversion is needed:
Beyond Kubernetes and CI/CD, JSON and YAML each have established territories in the broader configuration landscape. Understanding these conventions helps you choose the right format for your project.
package.json, tsconfig.json, package-lock.json, and .eslintrc.json.Content-Type: application/json header is ubiquitous.settings.json, launch.json, tasks.json, extensions.json.application.yml for configuration, taking advantage of YAML's hierarchical syntax.database.yml), internationalization files, fixtures, and credentials.When starting a new project and you have a choice, consider these guidelines:
YAML's flexibility and implicit type coercion are the source of many subtle bugs. Being aware of these pitfalls helps you write correct YAML and understand why converting between JSON and YAML sometimes produces unexpected results.
This is perhaps the most infamous YAML gotcha. In YAML 1.1, the unquoted values NO, no, No, and many other strings are interpreted as boolean false. This means a list of country codes can silently lose data:
# YAML 1.1 interpretation
countries:
- GB # string "GB"
- IE # string "IE"
- FR # string "FR"
- NO # boolean false (!)
- DK # string "DK"
Converting this YAML to JSON would produce "NO": false instead of "NO": "NO". The fix is simple: quote the value ("NO"). YAML 1.2 significantly reduced this problem by only treating true and false (lowercase) as booleans, but many parsers still use YAML 1.1 rules by default.
YAML's reliance on indentation means that a single misplaced space can silently change the meaning of a document. Unlike Python, YAML does not always produce an error for inconsistent indentation -- sometimes it just produces a different data structure:
# Intended: "ports" is a key under "spec"
spec:
ports:
- port: 80
# Bug: "ports" is a sibling of "spec" (wrong indentation)
spec:
ports:
- port: 80
JSON's explicit braces make this class of bug impossible. When debugging YAML indentation issues, converting to JSON reveals the actual structure the parser sees.
YAML explicitly forbids tab characters for indentation -- only spaces are allowed. Mixing tabs and spaces is a common error that produces confusing parse errors. Most editors can be configured to insert spaces when the Tab key is pressed, and YAML linters will flag tab characters.
Several common strings are parsed as non-string types in YAML when left unquoted:
| YAML Input | Parsed As | Expected |
|---|---|---|
version: 1.0 | Float 1.0 | String "1.0" |
version: 1.2.0 | String "1.2.0" | String "1.2.0" |
port: 0080 | Octal 64 | String "0080" |
time: 12:30 | Sexagesimal 750 | String "12:30" |
enabled: yes | Boolean true | String "yes" |
value: null | Null | String "null" |
date: 2026-03-12 | Date object | String "2026-03-12" |
The solution is to quote any value that should remain a string: version: "1.0", port: "0080", enabled: "yes".
YAML provides multiple ways to handle multi-line strings, and each behaves differently:
| (literal block scalar): Preserves newlines exactly as written. Trailing newlines are kept.|- (literal block scalar, strip): Same as | but removes the final trailing newline.|+ (literal block scalar, keep): Same as | but keeps all trailing newlines.> (folded block scalar): Replaces single newlines with spaces (folds lines). Double newlines become single newlines.>- (folded block scalar, strip): Same as > but removes the final trailing newline.Choosing the wrong style can result in unexpected whitespace in the converted JSON string. When converting YAML with multi-line strings to JSON, always verify the resulting string contains the correct newline characters.
Most programming languages have mature libraries for both JSON and YAML, making programmatic conversion straightforward.
Python's json module is built-in, and PyYAML is the most popular YAML library:
import json
import yaml
# JSON to YAML
with open('config.json') as f:
data = json.load(f)
with open('config.yaml', 'w') as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
# YAML to JSON
with open('config.yaml') as f:
data = yaml.safe_load(f)
with open('config.json', 'w') as f:
json.dump(data, f, indent=2)
Always use yaml.safe_load() instead of yaml.load(). The latter can execute arbitrary Python code from YAML tags, making it a security risk when processing untrusted input.
Node.js has built-in JSON support, and the js-yaml package is the standard YAML library:
const fs = require('fs');
const yaml = require('js-yaml');
// JSON to YAML
const jsonData = JSON.parse(fs.readFileSync('config.json', 'utf8'));
const yamlOutput = yaml.dump(jsonData, { lineWidth: -1, noRefs: true });
fs.writeFileSync('config.yaml', yamlOutput);
// YAML to JSON
const yamlData = yaml.load(fs.readFileSync('config.yaml', 'utf8'));
const jsonOutput = JSON.stringify(yamlData, null, 2);
fs.writeFileSync('config.json', jsonOutput);
Go has the standard library encoding/json and the popular gopkg.in/yaml.v3 package:
package main
import (
"encoding/json"
"fmt"
"os"
"gopkg.in/yaml.v3"
)
func main() {
// Read JSON file
jsonData, _ := os.ReadFile("config.json")
// Parse JSON into a generic structure
var data interface{}
json.Unmarshal(jsonData, &data)
// Convert to YAML
yamlData, _ := yaml.Marshal(data)
fmt.Println(string(yamlData))
}
Several command-line tools make quick conversions easy:
# Using yq (https://github.com/mikefarah/yq)
# JSON to YAML
yq -P input.json
# YAML to JSON
yq -o=json input.yaml
# Using Python one-liner (JSON to YAML)
python3 -c "import sys,json,yaml; yaml.dump(json.load(sys.stdin),sys.stdout,default_flow_style=False)" < input.json
# Using Python one-liner (YAML to JSON)
python3 -c "import sys,json,yaml; json.dump(yaml.safe_load(sys.stdin),sys.stdout,indent=2)" < input.yaml
# Using Ruby one-liner (JSON to YAML)
ruby -ryaml -rjson -e 'puts YAML.dump(JSON.parse(STDIN.read))' < input.json
Follow these guidelines to work effectively with JSON and YAML and avoid common conversion problems.
When authoring YAML, quote any value that could be misinterpreted as a non-string type. This includes version numbers ("1.0"), boolean-like strings ("yes", "no", "on", "off"), and strings that look like dates or numbers. When in doubt, quote it.
Choose 2 spaces (the most common convention) and stick with it throughout your project. Configure your editor to insert spaces instead of tabs for YAML files. Use a .editorconfig file to enforce this across your team:
# .editorconfig
[*.{yml,yaml}]
indent_style = space
indent_size = 2
insert_final_newline = true
Tools like yamllint catch common errors before they cause problems. Configure it to enforce consistent style and catch ambiguous values:
# .yamllint.yml
extends: default
rules:
line-length:
max: 120
truthy:
check-keys: true
indentation:
spaces: 2
indent-sequences: true
After converting between formats, validate that the converted output matches the original data. This is especially important when converting YAML to JSON, as implicit type coercion may have changed string values to booleans, numbers, or nulls. Compare the parsed data structures, not just the text representations.
Use JSON for API payloads, inter-service communication, and any context where data is primarily consumed by machines. JSON's strict syntax eliminates ambiguity, and its parsing performance is generally superior to YAML.
Use YAML for files that humans will regularly read, edit, and review in version control. The ability to add comments, avoid excessive quoting, and express structure through indentation makes YAML more maintainable for configuration management.
Always use safe loading functions when parsing YAML from untrusted sources. YAML's tag system allows arbitrary object instantiation in some parsers, which can lead to remote code execution vulnerabilities. Use yaml.safe_load() in Python, avoid yaml.load() without a Loader argument, and prefer YAML parsers that default to safe behavior.
When a project uses both JSON and YAML (which is common), document the convention. Specify which format is used for which purpose, and provide conversion instructions for team members who may need to convert between formats.
Our free JSON/YAML Converter tool makes it easy to convert between JSON and YAML directly in your browser. No data is sent to any server -- all processing happens locally on your machine.
Paste your JSON data and instantly get clean, properly formatted YAML output. The converter handles nested objects, arrays, strings with special characters, and all JSON data types. The output uses consistent 2-space indentation and applies appropriate quoting rules for YAML values.
Paste your YAML configuration and get valid, well-formatted JSON output. The converter correctly handles YAML-specific features like multi-line strings, anchors, aliases, and implicit type coercion. Error messages help you identify and fix YAML syntax issues before conversion.
Stop wrestling with manual format conversion. Use our free tool to convert JSON to YAML and YAML to JSON right in your browser -- with zero data sent to any server.
Try the JSON/YAML Converter NowJSON uses braces, brackets, and double-quoted strings with strict syntax, making it ideal for machine-to-machine communication and APIs. YAML uses indentation-based structure, supports comments, multi-line strings, and anchors/aliases, making it more readable and preferred for configuration files. Since YAML 1.2, YAML is a superset of JSON.
Yes. Every JSON data type has a direct YAML equivalent, so conversion is lossless. However, converting YAML to JSON may lose YAML-specific features like comments, anchors, aliases, and multi-line string formatting, since JSON does not support these constructs.
YAML is preferred for Kubernetes because it supports comments for documentation, allows multiple resources in a single file with --- separators, handles multi-line strings cleanly for embedded scripts, and produces more readable diffs in code review. However, Kubernetes fully supports JSON as well.
Yes, since YAML 1.2, any valid JSON document is also valid YAML. YAML parsers can parse JSON directly. The reverse is not true -- YAML features like comments, anchors, and complex keys have no JSON representation.
The most common pitfalls include incorrect indentation, using tabs instead of spaces, unquoted strings parsed as booleans (the "Norway problem" where NO becomes false), version numbers parsed as floats (1.0 instead of "1.0"), and octal interpretation of zero-padded numbers. Always quote ambiguous values.
Use yq -P input.json to convert JSON to YAML, or yq -o=json input.yaml for the reverse. You can also use Python one-liners with the json and yaml modules, or our free online JSON/YAML Converter tool.
Master JSON syntax, formatting best practices, validation techniques, and common parsing errors.
Master Kubernetes YAML from Deployments and Services to advanced scheduling and security contexts.
Master cron syntax, scheduling patterns, and common expressions for automating tasks on Unix systems.