JSON ↔ YAML Converter

Convert JSON to YAML and YAML to JSON for configs, Kubernetes manifests and API specs.

JSON to YAML and YAML to JSON Converter: OpenAPI, Kubernetes and Config Files

Pick a direction, paste JSON or YAML, and the converted text appears as you type. JSON to YAML produces block-style YAML with two-space indentation; YAML to JSON produces JSON pretty-printed with two spaces. Both directions use the `yaml` library for JavaScript, version 2, which follows the YAML 1.2 specification, so the input is parsed into data and written out again rather than patched with find-and-replace. Syntax errors are shown with the line and column.

JSON to YAML

Objects become indented mappings, arrays become lists of - items, and key order is kept exactly as in the JSON. Strings are written without quotes unless YAML would read them as something else, in which case the converter quotes them:

{"name": "api", "version": "1.10", "mode": "0755", "enabled": true,
 "tags": ["json", "yaml"], "note": "a: b", "empty": {}}

name: api
version: "1.10"
mode: "0755"
enabled: true
tags:
  - json
  - yaml
note: "a: b"
empty: {}

The quotes around "1.10" and "0755" are what keep them strings: unquoted, a YAML parser would read them as the numbers 1.1 and 755. Strings containing line breaks are written as literal blocks with |, and strings longer than 80 characters are folded onto several lines, which is purely cosmetic: a parser joins them back into the same string.

YAML to JSON

Paste YAML and get JSON indented with two spaces. Because YAML 1.2 is a superset of JSON for practical purposes, you can also paste JSON in this mode to reformat it. A few things have no JSON equivalent, and it helps to know what happens to them before you rely on the output:

# comments                     removed: JSON has no comments
base: &defaults                anchors and aliases: expanded, the data is copied
copy: *defaults
text: |                        block strings: become "line one\nline two\n"
  line one
  line two
date: 2024-01-15               stays the string "2024-01-15"
inf: .inf                      becomes null: JSON has no Infinity
big: 12345678901234567890      becomes 12345678901234567000

The last line is a JavaScript limit rather than a YAML one: numbers are stored as 64-bit floats, so integers above 2^53 lose precision. Keep IDs and account numbers of that size as quoted strings. Mapping keys must be unique; a: 1 followed by a: 2 is reported as an error instead of silently keeping the last value, and tabs used for indentation are rejected, because YAML allows only spaces.

NO, yes and 0755: YAML 1.2 versus 1.1

The best-known YAML trap is the Norway problem: in YAML 1.1, NO, no, off, yes and on are booleans, so a list of country codes loses Norway. YAML 1.2, published in 2009, reduced booleans to true and false, and this converter follows 1.2. Here is the same YAML read by the converter and by PyYAML 6.0, which implements YAML 1.1:

input          this converter (1.2)    PyYAML safe_load (1.1)
country: NO    "NO"                    False
switch: off    "off"                   False
mode: 0755     755                     493  (octal)
mode: 0o755    493                     "0o755"
date: 2024-01-15   "2024-01-15"        datetime.date(2024, 1, 15)
count: 1_000   "1_000"                 1000

Both parsers are correct for their version of the specification, which is exactly the problem. When JSON to YAML output will be read by a YAML 1.1 parser, such as PyYAML or older Go and Ruby tooling, quote values like NO, off, yes and dates yourself. The converter only quotes what is ambiguous under YAML 1.2, so country: NO comes out unquoted. For file permissions, write 0o755 or the decimal 493 if the consumer expects YAML 1.2, and check which one it expects before a deploy changes a mode to 755.

Anchors, merge keys and custom tags

Aliases such as *defaults are resolved, so the JSON contains a full copy of the anchored data at each place it is used. The merge key <<, common in Docker Compose and CI files, comes from YAML 1.1 and is not part of the YAML 1.2 specification, but the converter applies it the way Docker Compose does: <<: *defaults copies the anchored keys into the surrounding mapping, and keys written next to it override them. Some strict YAML 1.2 parsers do not, and keep a literal << key instead, so check the parser your application uses before relying on merge keys.

Application-specific tags, such as AWS CloudFormation's !Ref and !Sub, are not understood. The tag is dropped and only its value is kept, so !Ref MyBucket becomes the plain string "MyBucket". That is fine for reading a template, but not for converting it back: CloudFormation accepts JSON templates, where the same thing is written as {"Ref": "MyBucket"}.

Converting OpenAPI and Swagger files

OpenAPI (formerly Swagger) documents may be written in JSON or YAML, and the specification recommends YAML 1.2 and limits tags and keys so that a document can round-trip between the two; tools such as Swagger UI and Redoc read both. Converting a swagger.json or openapi.json to YAML is usually done to make the file easier to review. Paths with braces and quoted status codes come through correctly:

openapi: 3.0.3
paths:
  /users/{id}:
    get:
      responses:
        "200":
          description: OK

"200" stays quoted because response codes are strings in OpenAPI; without the quotes, a parser would produce the integer 200. The spec's openapi: 3.0.3 field needs no quotes, because 3.0.3 is not a valid number. version: 1.0 in an info block does: without quotes, 1.0 is a float and becomes 1 in JSON.

Multiple documents and converting in code

A YAML file can hold several documents separated by ---, as Kubernetes manifests often do. JSON has no equivalent, so the converter reports an error for multi-document input; convert one document at a time, or wrap them in a JSON array in code:

// JavaScript, yaml v2
import YAML from 'yaml';
const data = YAML.parse(text);                        // one document
const all = YAML.parseAllDocuments(text).map(d => d.toJS());
const yaml = YAML.stringify(JSON.parse(json));

# Python: PyYAML follows YAML 1.1, see the table above
import json, yaml
data = yaml.safe_load(text)
print(yaml.safe_dump(json.loads(raw), sort_keys=False))

# shell, mikefarah/yq v4
yq -o=json config.yaml
yq -P config.json

Two details catch people in Python: yaml.safe_dump sorts keys alphabetically unless you pass sort_keys=False, and yaml.load without a safe loader can construct arbitrary Python objects from tagged input. Use safe_load for anything you did not write yourself.

Private conversion

Configuration files contain hostnames, internal service names and sometimes credentials. The conversion happens in your browser with no request to a server, so nothing you paste is sent or stored.

Frequently asked questions

How do I convert JSON to YAML?

Choose JSON to YAML and paste the JSON. The YAML appears immediately, with two-space indentation, the original key order, and quotes only where a value would otherwise change type.

How do I convert YAML to JSON?

Choose YAML to JSON and paste the YAML. The result is JSON indented with two spaces; comments are removed and anchors are expanded, because JSON has no equivalent for either.

Why does NO stay a string instead of becoming false?

The converter follows YAML 1.2, where only true and false are booleans. YAML 1.1 parsers such as PyYAML read NO, off and yes as booleans, so quote such values if a 1.1 parser will read your file.

Can I convert a Kubernetes file with several documents?

Not in one go. JSON has no multi-document format, so input with several documents separated by --- is reported as an error. Convert each document separately.

Can I convert an OpenAPI or Swagger JSON file to YAML?

Yes. Paste the openapi.json or swagger.json file in JSON to YAML mode. Keys keep their order and status codes such as 200 stay quoted strings, so the YAML describes the same API.

Is my file uploaded anywhere?

No. Parsing and conversion run in your browser, and the text you paste is not sent to a server or stored.