Tools: Latest: YAML vs JSON: When to Use Each and How to Convert Between Them

Tools: Latest: YAML vs JSON: When to Use Each and How to Convert Between Them

At a glance

When to use JSON

When to use YAML

YAML features that JSON lacks

Converting between formats

YAML pitfalls for developers YAML and JSON both represent structured data, but they're optimized for different use cases. Here's when to use each and how to convert between them. API responses and requests: JSON is the standard. It's compact, fast to parse, and universally supported. Every language has built-in JSON parsing. Data storage: When you're storing structured data that will be read by machines (database, message queues, event payloads), JSON's strictness is a feature — less ambiguity means fewer parsing edge cases. Config files that are code-generated: If a tool writes the config file, JSON's strict format is easier to generate correctly. Configuration files humans will edit: YAML's lack of braces and quotes makes it dramatically more readable for humans. This is why Kubernetes manifests, GitHub Actions, Docker Compose, Ansible playbooks, and many other tools use YAML — these files are written and maintained by people. When you need comments: JSON has no comment syntax. YAML comments ({% raw %}# this is a comment) are essential for documenting configuration options. Multi-line strings: YAML has clean syntax for literal blocks (|) and folded strings (>): The JSON equivalent requires \n escaping: Anchors and aliases (DRY config): This is impossible in JSON — repeated configuration must be duplicated. Multiple documents in one file: Used extensively in Kubernetes to deploy multiple resources from a single file. YAML 1.1 (the version many tools use) parses certain strings as booleans: This is a common source of bugs in YAML config. If you mean the string "yes" or "no", quote it: YAML 1.2 (2009+) removed most of these ambiguities, but tool support varies. For one-off conversions: A YAML ↔ JSON converter handles the conversion in the browser without any setup. Tabs are not allowed for indentation. YAML specifically forbids tabs. If you paste YAML from a source that uses tabs, the parser will error. Indentation creates structure. Unlike JSON, YAML's structure is defined entirely by indentation. Misalign a key by one space and the structure changes silently. Numbers can surprise you: Practical YAML validation: Run yamllint before committing config files: It catches tab characters, missing blank lines before lists, and other style issues that cause silent parsing problems. Use JSON for APIs and machine-to-machine data. Use YAML for human-maintained config files where readability and comments matter. When converting between them, be aware of YAML's boolean and number auto-conversion quirks — those are the most common source of conversion bugs. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

description: | This is a multi-line string. Each line is preserved exactly. No escaping needed. folded_description: > This is a folded string. These lines will be joined with spaces into one long line. description: | This is a multi-line string. Each line is preserved exactly. No escaping needed. folded_description: > This is a folded string. These lines will be joined with spaces into one long line. description: | This is a multi-line string. Each line is preserved exactly. No escaping needed. folded_description: > This is a folded string. These lines will be joined with spaces into one long line. { "description": "This is a multi-line string.\nEach line is preserved exactly.\nNo escaping needed." } { "description": "This is a multi-line string.\nEach line is preserved exactly.\nNo escaping needed." } { "description": "This is a multi-line string.\nEach line is preserved exactly.\nNo escaping needed." } defaults: &defaults image: node:20-alpine timeout: 300 build: <<: *defaults command: npm run build test: <<: *defaults command: npm test timeout: 600 # Override defaults defaults: &defaults image: node:20-alpine timeout: 300 build: <<: *defaults command: npm run build test: <<: *defaults command: npm test timeout: 600 # Override defaults defaults: &defaults image: node:20-alpine timeout: 300 build: <<: *defaults command: npm run build test: <<: *defaults command: npm test timeout: 600 # Override defaults --- kind: Deployment metadata: name: my-app --- kind: Service metadata: name: my-app-service --- kind: Deployment metadata: name: my-app --- kind: Service metadata: name: my-app-service --- kind: Deployment metadata: name: my-app --- kind: Service metadata: name: my-app-service # These are booleans in YAML 1.1, NOT strings: enabled: yes # true disabled: no # false active: on # true inactive: off # false # These are booleans in YAML 1.1, NOT strings: enabled: yes # true disabled: no # false active: on # true inactive: off # false # These are booleans in YAML 1.1, NOT strings: enabled: yes # true disabled: no # false active: on # true inactive: off # false country: "no" # Norway's country code — NOT a boolean answer: "yes" # The word "yes" — NOT a boolean country: "no" # Norway's country code — NOT a boolean answer: "yes" # The word "yes" — NOT a boolean country: "no" # Norway's country code — NOT a boolean answer: "yes" # The word "yes" — NOT a boolean import yaml, json # JSON to YAML json_str = '{"name": "Alice", "active": true}' data = json.loads(json_str) yaml_str = yaml.dump(data, default_flow_style=False) # YAML to JSON yaml_str = "name: Alice\nactive: true\n" data = yaml.safe_load(yaml_str) json_str = json.dumps(data, indent=2) # File conversion with open('config.yaml') as f: data = yaml.safe_load(f) with open('config.json', 'w') as f: json.dump(data, f, indent=2) import yaml, json # JSON to YAML json_str = '{"name": "Alice", "active": true}' data = json.loads(json_str) yaml_str = yaml.dump(data, default_flow_style=False) # YAML to JSON yaml_str = "name: Alice\nactive: true\n" data = yaml.safe_load(yaml_str) json_str = json.dumps(data, indent=2) # File conversion with open('config.yaml') as f: data = yaml.safe_load(f) with open('config.json', 'w') as f: json.dump(data, f, indent=2) import yaml, json # JSON to YAML json_str = '{"name": "Alice", "active": true}' data = json.loads(json_str) yaml_str = yaml.dump(data, default_flow_style=False) # YAML to JSON yaml_str = "name: Alice\nactive: true\n" data = yaml.safe_load(yaml_str) json_str = json.dumps(data, indent=2) # File conversion with open('config.yaml') as f: data = yaml.safe_load(f) with open('config.json', 'w') as f: json.dump(data, f, indent=2) const yaml = require('js-yaml'); const fs = require('fs'); // YAML to JSON const yamlContent = fs.readFileSync('config.yaml', 'utf8'); const data = yaml.load(yamlContent); const jsonContent = JSON.stringify(data, null, 2); // JSON to YAML const jsonContent2 = fs.readFileSync('config.json', 'utf8'); const data2 = JSON.parse(jsonContent2); const yamlContent2 = yaml.dump(data2); const yaml = require('js-yaml'); const fs = require('fs'); // YAML to JSON const yamlContent = fs.readFileSync('config.yaml', 'utf8'); const data = yaml.load(yamlContent); const jsonContent = JSON.stringify(data, null, 2); // JSON to YAML const jsonContent2 = fs.readFileSync('config.json', 'utf8'); const data2 = JSON.parse(jsonContent2); const yamlContent2 = yaml.dump(data2); const yaml = require('js-yaml'); const fs = require('fs'); // YAML to JSON const yamlContent = fs.readFileSync('config.yaml', 'utf8'); const data = yaml.load(yamlContent); const jsonContent = JSON.stringify(data, null, 2); // JSON to YAML const jsonContent2 = fs.readFileSync('config.json', 'utf8'); const data2 = JSON.parse(jsonContent2); const yamlContent2 = yaml.dump(data2); # Python (no dependencies) python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yaml # Or pipe: cat config.yaml | python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" # yq (the jq for YAML — install: pip install yq or brew install yq) yq -j '.' config.yaml # YAML to JSON cat data.json | yq -y '.' # JSON to YAML # Python (no dependencies) python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yaml # Or pipe: cat config.yaml | python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" # yq (the jq for YAML — install: pip install yq or brew install yq) yq -j '.' config.yaml # YAML to JSON cat data.json | yq -y '.' # JSON to YAML # Python (no dependencies) python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yaml # Or pipe: cat config.yaml | python3 -c "import sys, json, yaml; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" # yq (the jq for YAML — install: pip install yq or brew install yq) yq -j '.' config.yaml # YAML to JSON cat data.json | yq -y '.' # JSON to YAML country_codes: - no # Parses as false (boolean) in YAML 1.1! - gb - us country_codes: - no # Parses as false (boolean) in YAML 1.1! - gb - us country_codes: - no # Parses as false (boolean) in YAML 1.1! - gb - us version: 1.0 # float, not "1.0" string port: 8080 # integer hex: 0x1F # integer (31) — if you wanted the string "0x1F", quote it version: 1.0 # float, not "1.0" string port: 8080 # integer hex: 0x1F # integer (31) — if you wanted the string "0x1F", quote it version: 1.0 # float, not "1.0" string port: 8080 # integer hex: 0x1F # integer (31) — if you wanted the string "0x1F", quote it pip install yamllint yamllint kubernetes/ pip install yamllint yamllint kubernetes/ pip install yamllint yamllint kubernetes/