JSON to YAML Converter

Output
Examples:

Last updated: 2026-09-17

Paste JSON and get formatted YAML output. Key order is preserved from the original JSON. The converter handles nested objects, arrays, Unicode strings, and special characters that require quoting in YAML. No data leaves your browser.

What this tool does

Converts a JSON document into YAML 1.2 output with 2-space indentation. The conversion is lossless: every JSON type (object, array, string, number, boolean, null) maps to an equivalent YAML type. Key order is preserved. The output uses no anchors, aliases, or tags, making it portable across YAML parsers.

The converter runs entirely in your browser. Pasted input is parsed with the standard JSON parser, passed through js-yaml configured with indent: 2, lineWidth: 120, noRefs: true, and sortKeys: false, then rendered in the output panel. Nothing is sent to a server, stored, or logged, which makes the tool suitable for secrets, credentials, and internal configuration that must not leave your machine.

Example

Input:

{"server":{"host":"localhost","port":8080},"features":["auth","logging","cache"],"debug":false}

Output:

server:
  host: localhost
  port: 8080
features:
  - auth
  - logging
  - cache
debug: false

JSON vs YAML: key differences

FeatureJSONYAML
Quotes on keysRequired (double)Optional
CommentsNot allowed (RFC 8259)Allowed (# only)
Multi-documentNot supportedSupported via ---
Anchors/aliasesNot supportedSupported (& and *)
Booleanstrue / false onlyYAML 1.1: yes/no/on/off; YAML 1.2: true/false
Nullnullnull, ~, or empty
Line breaks\n escapeLiteral or folded block scalars
Trailing commasNot allowedNot allowed

YAML block styles

YAML has two families of scalar presentation: plain (unquoted) and quoted (single or double), plus two block scalar indicators for multi-line content: literal (|) and folded (>). The converter picks a presentation per value based on what the string contains.

Collections have two presentations as well. Block style uses indentation for mappings and a dash-prefixed list for sequences. Flow style uses braces {} and brackets [] with commas, resembling JSON. The converter emits block style for every non-empty mapping and sequence. Empty objects and empty arrays are the only flow-style output, written as {} and [] respectively.

The lineWidth: 120 option governs where flow-style content and long plain scalars wrap. With the limit set to 120 characters, a long flow collection breaks onto multiple lines only after exceeding 120 columns. Block-style collections are not affected by line width because they are already structured by indentation.

Single-quoted strings are not emitted by the converter, but worth knowing: single quotes differ from double quotes in YAML because they cannot represent all escape sequences and escape a lone single quote by doubling it. The converter consistently uses double quotes when quoting is required, so you will not see single-quoted output even for strings that contain an apostrophe.

When to use YAML instead of JSON

YAML is the preferred format for configuration files in ecosystems like Kubernetes, GitHub Actions, OpenAPI, and docker-compose. Its indentation-based structure and comment support make it more readable than JSON for hand-edited files. JSON is better for data interchange between systems: it is simpler, has a smaller parsing surface, and every JSON parser handles it identically.

For large payloads, prefer JSON. YAML parsers are slower and more memory-hungry than JSON parsers because the grammar is larger and indentation must be tracked. A multi-megabyte YAML document can take noticeably longer to load than the equivalent JSON, and the readability gains of indentation vanish at that scale anyway. Streaming parsers exist for both formats, but JSON streaming is more mature and widely deployed in production pipelines.

Converting Kubernetes manifests

A Kubernetes manifest stored as JSON converts cleanly to YAML because the data is nested mappings and sequences with string and number values. Given this JSON input:

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "api-server",
    "namespace": "production",
    "labels": {"app": "api", "tier": "backend"}
  },
  "spec": {
    "replicas": 3,
    "selector": {"matchLabels": {"app": "api"}},
    "template": {
      "metadata": {"labels": {"app": "api", "tier": "backend"}},
      "spec": {
        "containers": [
          {
            "name": "api",
            "image": "registry.example.com/api:1.4.2",
            "ports": [{"containerPort": 8080}],
            "env": [{"name": "LOG_LEVEL", "value": "info"}]
          }
        ]
      }
    }
  }
}

The converter produces indented YAML with the same key order, 2-space indentation, and single-item sequences rendered as block lists. The matchLabels mapping, the containers sequence, and the nested template.spec all stay in block style. Strings such as apps/v1 remain unquoted because the slash is not a special character in YAML plain scalars. The numeric value 3 for replicas stays a number, and 8080 stays an integer rather than becoming a string.

Because the manifest mixes single-element arrays (one container, one port, one environment variable) with multi-key mappings, the block-style output spreads each value onto its own line. Sequence items begin with a dash and a space, and their nested keys align under the first letter of the item. This alignment matters when you diff manifests across revisions: identical key order means an unchanged field stays on the same line, so pull request reviewers see only the lines that actually changed.

Converting GitHub Actions workflows

GitHub Actions workflows are large YAML documents that teams sometimes generate from JSON templates. Converting the JSON form back to YAML keeps the key order that GitHub expects. Given this JSON input:

{
  "name": "CI",
  "on": {
    "push": {"branches": ["main"]},
    "pull_request": null
  },
  "permissions": {"contents": "read"},
  "jobs": {
    "build": {
      "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"}
      ]
    }
  }
}

The converter emits a workflow document where the on key, the push mapping, and each entry in the steps sequence are indented consistently. The null value for pull_request becomes null in the YAML output, matching YAML 1.2. Step entries that mix uses, with, and run keys render as block mappings inside the sequence. String values like ubuntu-latest and actions/checkout@v4 stay plain because hyphens, dots, and at-signs do not trigger quoting in YAML plain scalars.

Note: the on key is a YAML 1.1 boolean in some parsers. The converter writes it unquoted because js-yaml targets YAML 1.2, where on is not a boolean. If your downstream tooling parses with YAML 1.1 rules, quote the key manually as "on":.

Workflows benefit from conversion because teams frequently maintain the canonical definition in JSON (often generated by a policy tool or templating engine) and render it to YAML for the repository. Round-tripping through this converter keeps the structure intact: job names, step ordering, matrix dimensions, and environment variable lists all preserve their original sequence. When a step contains only a uses key, it renders as a one-line mapping; when a step adds a with block, the block indents two spaces beneath the step entry.

Gotchas

The Norway problem. In YAML 1.1, the two-letter country code NO is interpreted as boolean false. The same applies to yes, no, on, off, Y, and N. This converter uses YAML 1.2 conventions (only true/false), but downstream parsers may use YAML 1.1. Quote such values to force them to remain strings.

Date-like strings. A value like 2024-01-15 matches the YAML date pattern and may be parsed as a date object by some YAML loaders. Wrap it in quotes if it should stay a string.

Numbers as strings. Values like 0123 may be interpreted as octal in YAML 1.1. Quote them to preserve the string representation.

Indentation. YAML uses indentation for structure, not braces. A single wrong space can change the document structure. This converter produces consistent 2-space indentation, but if you edit the output by hand, be careful. A common failure is outdented sequence items: a dash that sits at the same column as the parent mapping key detaches the items from that key and attaches them to the enclosing context.

Common mistakes when converting JSON to YAML

Do it in code

Node.js (js-yaml):

const yaml = require('js-yaml');
const json = '{"name":"test","value":42}';
const output = yaml.dump(JSON.parse(json), { indent: 2, noRefs: true, sortKeys: false });
console.log(output);

To match this converter exactly, also pass lineWidth: 120. The dump options used here mirror the tool: indent controls the number of spaces per nesting level, noRefs prevents anchor and alias output for repeated object references, and sortKeys: false keeps the original insertion order. The converter never sets flowLevel, so all nested collections render in block style rather than collapsing into inline braces at a given depth.

Python (PyYAML):

import json, yaml
data = json.loads('{"name":"test","value":42}')
print(yaml.dump(data, sort_keys=False, allow_unicode=True))

CLI (jq + yq):

echo '{"name":"test","value":42}' | jq '.' | yq -y '.'

Note: yq here refers to the Python-based yq (pip install yq), which wraps jq. The Go-based yq (mikefarah/yq) uses a different syntax.

Round-tripping JSON through YAML

Converting a JSON document to YAML and then parsing it back should, in principle, reproduce the original data unchanged. Both formats describe the same core structures—mappings, sequences, and scalars—so a faithful round trip preserves types, values, and nesting. In practice, several pitfalls can alter the result before you notice.

Date-like strings are the most frequent surprise. A value such as 2024-01-15 is a plain string in JSON, but many YAML loaders promote it to a native date object, which then serializes differently when written back to disk. Large integers can lose precision when a loader coerces them into floating-point representations, dropping trailing digits or shifting exponent boundaries. Duplicate keys, which the JSON parser already collapses to the final occurrence, vanish entirely after the round trip, hiding earlier values from anyone reviewing the output afterward.

To guarantee fidelity, quote date-like strings before conversion, keep integers within safe numeric ranges, and eliminate duplicate keys at the source rather than relying on the converter to surface them. When absolute equivalence matters, diff the round-tripped output against the original payload programmatically.

Edge cases handled

Frequently asked questions

Is key order preserved?
Yes. The converter uses sortKeys: false, so keys appear in the same order as in the original JSON. JavaScript objects preserve insertion order for string keys, and that order carries through to the YAML output.
How are special characters handled?
The YAML dumper automatically quotes values that contain special characters like colons, hashes, or leading spaces. Strings with newlines use YAML block scalars or are quoted as needed.
Can I convert multiple JSON objects to multi-document YAML?
This converter takes a single JSON input. If you need multi-document YAML, wrap your objects in a JSON array — each element becomes a separate YAML document when you use a multi-document YAML converter.
Does it support YAML anchors and aliases?
No. The converter disables anchors and aliases (noRefs: true) to produce clean, portable YAML. If your JSON contains circular references, they are detected and reported as an error rather than producing YAML anchors.
What about Unicode?
Unicode characters are preserved in the YAML output. The converter does not escape non-ASCII characters, so Japanese, Chinese, emoji, and other Unicode text appears as-is in the YAML.

Related converters