Blog

How to convert YAML to JSON online

How YAML maps to JSON, the indentation rules that trip people up, how to convert in code or on the command line, and what changes in the conversion.

February 10, 2026

You copy a block out of a Kubernetes manifest, paste it into a script that expects JSON, and get a parse error. Fair enough: YAML and JSON hold the same data, but they spell it very differently.

This guide shows how the two map onto each other, the indentation rules that catch everyone at least once, and what quietly changes when you convert.

What YAML is

YAML (YAML Ain’t Markup Language) is a data format designed to be easy for people to read and write. Instead of braces and brackets, it uses indentation and line breaks to show structure, so a YAML file reads like an outline.

It's the usual configuration format for Kubernetes, Docker Compose, GitHub Actions, GitLab CI, Ansible and Helm. Many APIs and libraries expect JSON instead, so you’ll find yourself converting between the two more often than you’d think.

YAML and JSON side by side

Both formats describe the same kinds of data: objects (mappings in YAML), arrays (sequences) and scalars, which are single values such as strings, numbers, booleans and null. Here is the same configuration in each:

config.yaml
# Application configuration
app:
  name: PulpMiner
  version: 2.4.1
  debug: false

server:
  host: 0.0.0.0
  port: 8080

database:
  host: db.example.com
  port: 5432
  credentials:
    username: admin
    password: secret123

features:
  - name: scraping
    enabled: true
  - name: scheduling
    enabled: false
config.json
{
  "app": {
    "name": "PulpMiner",
    "version": "2.4.1",
    "debug": false
  },
  "server": {
    "host": "0.0.0.0",
    "port": 8080
  },
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "credentials": {
      "username": "admin",
      "password": "secret123"
    }
  },
  "features": [
    { "name": "scraping", "enabled": true },
    { "name": "scheduling", "enabled": false }
  ]
}

The YAML version is shorter, allows comments (lines starting with #) and doesn't need quotes around most strings. Types are inferred: 8080 is a number, false is a boolean, and 2.4.1 is a string because it isn't a valid number.

YAML indentation rules

Indentation decides the structure, so getting it wrong either changes your data or causes a parse error. YAML may be the only format where two stray spaces can take down a deploy.

  • Use spaces, not tabs. YAML doesn't allow tabs for indentation.
  • Keep siblings aligned. Keys at the same level must start in the same column. Any width works, but two spaces per level is the convention.
  • Indent children further than their parent. A key at the same column as the one above it is a sibling, not a child.
  • Start list items with a dash and a space (- ), all at the same indentation.
YAML
# Correct: host and port belong to server
server:
  host: localhost
  port: 3000

# Wrong: host and port are siblings of server, which is null
server:
host: localhost
port: 3000

# Correct: list items under the key
fruits:
  - apple
  - banana

# Wrong: port is indented further than its sibling
database:
  host: localhost
    port: 5432

Where you meet YAML

Kubernetes

Kubernetes manifests describe the desired state of an application: the container image, replica count, resource limits and more. kubectl accepts the same manifest as JSON, and kubectl get ... -o json prints resources as JSON.

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: myregistry/web-app:1.2.0
          ports:
            - containerPort: 8080
          resources:
            limits:
              memory: "256Mi"
              cpu: "500m"

Docker Compose

Compose files define multi-container applications. Run docker compose config --format json to see the fully resolved file as JSON.

compose.yaml
services:
  web:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: myapp
      POSTGRES_PASSWORD: secret

volumes:
  pgdata:

GitHub Actions

Workflow files are YAML. Converting them to JSON is handy when you want to generate or check them with a script.

.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
      - run: npm ci
      - run: npm test

Converting YAML to JSON in code

JavaScript (Node.js)

Using the yaml package (npm install yaml):

JavaScript
import { readFileSync, writeFileSync } from "node:fs";
import { parse } from "yaml";

const data = parse(readFileSync("config.yaml", "utf-8"));
writeFileSync("config.json", JSON.stringify(data, null, 2));

Python

Using PyYAML (pip install pyyaml). Always use safe_load, which doesn't construct arbitrary Python objects.

Python
import json
import yaml

with open("config.yaml") as f:
    data = yaml.safe_load(f)

with open("config.json", "w") as f:
    # default=str turns dates into strings instead of raising TypeError
    json.dump(data, f, indent=2, default=str)

Command line with yq

yq converts in both directions:

Shell
brew install yq

# YAML to JSON
yq -o=json config.yaml > config.json

# JSON to YAML
yq -p=json -o=yaml config.json > config.yaml

# From stdin
cat config.yaml | yq -o=json

What changes in the conversion

Some YAML features have no JSON equivalent:

  • Comments are dropped. JSON has no comment syntax.
  • Anchors and aliases are expanded. YAML lets you define a value once with &name and reuse it with *name. In JSON the value is simply repeated.
  • Multi-line strings become escaped strings. Literal (|) blocks keep their line breaks as \n. Folded (>) blocks join lines with spaces.
  • Types are inferred, and parsers disagree. YAML 1.1 parsers such as PyYAML read yes, no, on and off as booleans. YAML 1.2 parsers, including the JavaScript yaml package, keep them as strings. Quote any value you want to stay a string.
YAML
enabled: yes       # true in YAML 1.1, "yes" in YAML 1.2
empty: null        # null (so are ~ and an empty value)
version: 1.0       # the number 1.0, written as 1 in JSON
octal: 0o777       # 511 in YAML 1.2
date: 2026-02-10   # PyYAML returns a date object

# Quote values to keep them as strings
enabled: "yes"
version: "1.0"
date: "2026-02-10"

Using the YAML and JSON converter

  1. Open the YAML and JSON converter and pick YAML to JSON or JSON to YAML.
  2. Paste your input and select Convert. If the input can't be parsed, the error message is shown instead of output.
  3. Copy the result, or select Swap to move the output into the input and convert it back the other way.

The converter runs in your browser, so nothing you paste leaves your machine. It handles nested mappings and lists, quoted strings, inline [a, b] and {a: b} values, | and > blocks and comments. Like YAML 1.1, it reads yes and no as booleans. It doesn't support anchors, aliases or files with several documents; use yq for those.

Need data from a webpage as JSON?

PulpMiner turns any public page into structured JSON and can save it as a live API. See it work on a demo page, no sign-up.

Try it on a demo page