JSON to YAML Converter
Convert JSON to YAML for config files and human-readable docs while keeping structure intact.
A JSON document is already valid YAML, so this conversion is not about making the data loadable — it is about the choices an emitter makes on your behalf. Where the quotes go, whether a list is indented, how a string with newlines gets written: those decisions are what you will be reading in diffs for the next year, and different emitters decide them differently.
Your JSON is already valid YAML; what you are buying is block style
YAML 1.2 was defined so that every JSON document is also a YAML document. A conforming 1.2 parser loads your JSON file untouched, which means the conversion is not about compatibility. What it produces is block style — one key per line, structure carried by indentation instead of punctuation — and block style is the only form that reviews cleanly in a diff and accepts comments.
Flow style has not gone away, and it is still the right choice for short leaf values. ports: [80, 443] on one line beats three lines of dashes. Emitters treat this as a threshold rather than a per-node judgement: js-yaml takes a flowLevel (dumping with flowLevel: 1 turns everything below the first level into flow style, giving a: {b: [1, 2]}), and PyYAML has default_flow_style. Mixed output almost always means someone edited it by hand afterwards.
The corollary matters more than the syntax. Because the conversion re-emits everything in the emitter's style and cannot recover comments, a YAML file that humans maintain should never be round-tripped through a converter in a pre-commit hook. Convert once, then let the YAML be the source of truth.
Two-space indentation, and the argument about where dashes go
A sequence under a mapping key can be written flush with its key or indented one level, and both parse to exactly the same structure. This is not a matter of taste in practice, because the tools disagree: js-yaml emits the indented form (k: then - a), while PyYAML emits the flush form (k: then - a at column zero). Feed PyYAML's output to yamllint with its stock configuration and you get warnings, because the indentation rule defaults to indent-sequences: true.
Indentation must be spaces, never tabs, and the width is an emitter setting — two by default in both js-yaml and PyYAML, adjustable via indent. Two is worth keeping. YAML's readability advantage over JSON inverts somewhere around the fourth level of nesting, where a reader has to count columns to work out what a key belongs to, and a wider indent reaches that point sooner.
The setting that surprises people is line width. Both emitters wrap at 80 columns by default, and wrapping a long plain scalar does not just add a newline — js-yaml converts the value into a folded block scalar, so a 120-character URL in your JSON comes out as u: >- followed by two indented lines. It re-reads to the same string, but the diff churns whenever surrounding text shifts. Pass lineWidth: -1 in js-yaml, or a large width in PyYAML, to keep one value per line.
The strings an emitter has to quote, and which quote it picks
A plain scalar is only safe when it cannot be mistaken for something else, so the emitter quotes defensively. Feed js-yaml the JSON strings "true", "0644", "1.0", "~", "*star", "a: b", " x " and the empty string, and every one comes back single-quoted. Three separate reasons are at work: the value would otherwise resolve to a non-string type, it starts with an indicator character such as - ? : , [ ] & * ! | > % @, or it has leading or trailing space that a plain scalar would strip.
Two sequences force quoting from the middle of a string rather than its start. A colon followed by a space would end a key, and a space followed by # begins a comment — so a: see #4 loads as the string see with the rest discarded as a comment, while b: http://x/#f is untouched because there is no space before the hash. Emitters get this right; hand-edited YAML frequently does not.
Single and double quotes are not interchangeable. A single-quoted scalar has exactly one escape, '' for a literal apostrophe, and processes nothing else — so a single-quoted x\ny is four characters ending in a literal backslash and n, not a newline. Double-quoted scalars are the only style that interprets \n, \t, \\ and \uXXXX. Keys follow the same rules, plus one limit worth knowing: the spec restricts an implicit key to a single line and at most 1024 characters, though enforcement is uneven — js-yaml will happily load a 1030-character key that a stricter parser rejects.
Multi-line strings: literal, folded, and the chomping indicator
A JSON string containing newlines can be emitted as a double-quoted scalar full of \n escapes or as a block scalar, and block scalars are the reason people convert configuration to YAML in the first place. | is literal and keeps every line break; > is folded and replaces single line breaks with spaces. A shell script or a PEM certificate needs |. A paragraph of documentation can take >.
The chomping indicator controls only the trailing newlines, and it is the detail that breaks checksums. Plain | clips to exactly one trailing newline, |- strips all of them, and |+ keeps every one. Loading | over the lines a and b gives a\nb\n; the same content under |- gives a\nb. That final byte is real data, and it is the difference between a script that ends cleanly and a signature that will not verify.
Folded scalars do not fold everything. A line indented more than its neighbours is kept verbatim along with the breaks around it, so > over a, an indented keep, and b yields a\n keep\nb\n rather than one folded line. This is how you embed a code sample in a description, and also how a stray indent becomes a permanent hard break.
One more piece of syntax exists because the parser genuinely cannot guess. If the first line of a block scalar begins with a space, there is no way to tell content indentation from block indentation, so an explicit indentation indicator is required: |2 means the content sits two columns in. Without it js-yaml fails with bad indentation of a mapping entry. Emitters add the digit automatically; humans writing YAML by hand rarely do.
Key order, accidental aliases, and what you add by hand afterwards
PyYAML's yaml.dump sorts mapping keys alphabetically unless you pass sort_keys=False: dumping a two-key structure ordered z then a gives you a first. A config that was ordered by meaning comes back ordered by spelling, and the next diff is unreadable. js-yaml preserves insertion order, so the same conversion in two languages produces two different files.
Both emitters also generate anchors on their own when the same object appears twice in the structure being dumped. In js-yaml, dumping an object whose a and b keys point at one shared value produces &ref_0 on the first and *ref_0 on the second; noRefs: true expands them instead. Converting from a JSON string never triggers this, because parsing creates distinct objects — but building the structure in memory and dumping it does, and unexpected &ref_0 markers in your output are the tell.
Anchors you actually want have to be written by hand after conversion, since JSON has no way to express a reference. Define with &defaults, refer with *defaults, and merge into a mapping with <<: *defaults. The merge key is a YAML 1.1 type rather than part of the 1.2 core schema, so support is a property of your consumer, not of YAML: js-yaml and Docker Compose handle it, GitLab CI documents it as a feature, and GitHub Actions does not support anchors at all. Going the other way — and the type surprises waiting there — is covered on the YAML to JSON converter.
Related tools
Try these tools that work well with this one
YAML to JSON Converter
Convert YAML to JSON
CSV to JSON Converter
Convert CSV data to JSON
JSON to CSV Converter
Convert JSON arrays of objects to CSV
JSON to TOON Converter
Convert JSON to TOON to save tokens
TOON to JSON Converter
Convert TOON back to standard JSON
CSV to XML Converter
Convert CSV text to XML
Related guides
Tutorials and guides to get more from this tool
JSON vs YAML: Choosing the Right Config Format
Compare JSON vs YAML for configuration: pros and cons, readability, and when to use each in DevOps workflows.
The Ultimate Guide to Data Serialization: JSON, YAML, XML, and TOON
From legacy XML to modern JSON and TOON, explore the evolution of data serialization formats and when to use them.
JSON to Query String: simplifying API Requests in 2025
Learn how to convert nested JSON objects into URL-encoded query strings significantly simplifying your API development workflow.
ThenCatch is a free developer toolkit. Learn more about us.