JSON to YAML Converter
Quote it, or YAML decides what it means
Trouble with JSON to YAML surfaces later, when something reads the file back. JSON is explicit: a quoted string is a string, and 007 is not a legal number. YAML infers a type from unquoted text, and what it infers depends on which spec the parser follows: 1.1 and 1.2 resolve everyday values differently, and heavily used parsers still follow 1.1. PyYAML reads k: no as False today.
The Norway problem
Under YAML 1.1, no, yes, on and off are booleans in lower case, capitalised and upper case alike: NO, No and no all give false, though a mixed nO stays a string. A list of ISO country codes therefore loads Norway as false, and the region code ON becomes true. YAML 1.2 keeps only true and false, which is why one file behaves differently in two pipelines. Converters do defend themselves: dumping the string NO writes 'NO' in both PyYAML and js-yaml. The bite usually comes from later hand-editing, or a tool that emits plain scalars.
Numbers that quietly change
Version strings are the usual casualty. 1.10 is read as a float, and 1.10 and 1.1 are the same number, so the pin comes back as 1.1, under 1.1 and 1.2 parsers alike. 1.2.3 has two dots, is not a number, and survives untouched, which is why only some entries in one file break. Leading zeros split by version: 010 is octal 8 under YAML 1.1 and decimal 10 under a 1.2-style parser, so the zero is gone either way and the two disagree on the value. Postcodes, dialling codes and part numbers need quotes; so do dates.
| Unquoted | May be read as | Write |
|---|---|---|
| NO | false, under YAML 1.1 | "NO" |
| off | false, under YAML 1.1 | "off" |
| 010 | 8 octal in 1.1, 10 in 1.2 | "010" |
| 1.10 | 1.1, in 1.1 and 1.2 | "1.10" |
| 2026-08-09 | a date, not text | "2026-08-09" |
Tabs, comments and the trip back
Tabs are illegal as YAML indentation; only spaces count. Parsers flag the tab itself rather than some later line: PyYAML reports a character that cannot start any token, js-yaml that tab characters must not be used in indentation, both with a line and column. PyYAML also rejects a tab after the colon or trailing a value; tabs are safe only inside quoted or block scalars. Set the editor to insert spaces for .yaml and .yml.
Going back, JSON cannot carry everything YAML holds. Comments have no JSON syntax and are dropped; anchors and aliases lose their sharing and return as repeated values; multi-document streams split by --- have no single JSON equivalent. YAML 1.2 was aligned with JSON, so a .json file is normally valid YAML already: convert for readability and comments, not compatibility. The edges are real: PyYAML refuses tab-indented JSON, and duplicate keys are valid JSON but not valid YAML, so js-yaml errors where PyYAML keeps the last.
Share this tool with friends
Free to use, no sign-up, works on any phone.
Frequently Asked Questions
Because YAML 1.1 resolves no, yes, on and off as booleans when they are unquoted, in lower case, capitalised or upper case: NO, No and no all load as false, though a mixed form such as nO stays a string. A list of ISO country codes with NO in it therefore loads Norway as false, which is where the name "the Norway problem" comes from. Writing "NO" in quotes keeps it a string. YAML 1.2 narrows booleans to true and false, but parsers such as PyYAML still resolve the 1.1 way.
Almost always. YAML 1.2 was aligned with JSON, so a .json document normally parses in a YAML 1.2 reader unchanged, which is why you convert for readability, block style and comments rather than for compatibility. Two edges are worth knowing. JSON indented with real tabs is rejected by PyYAML, because tabs are not legal YAML indentation. And duplicate keys are valid JSON but not valid YAML: js-yaml raises a duplicated mapping key error, while PyYAML quietly keeps the last one.
No, indentation must be spaces. A tab there is a scan error, and both common parsers point at the tab itself rather than a line further down: PyYAML reports a character that cannot start any token, js-yaml that tab characters must not be used in indentation, each with a line and column. PyYAML is stricter still, rejecting a tab after the colon or trailing a value; tabs are safe only inside quoted or block scalars. Set the editor to insert spaces for .yaml and .yml files.
Because unquoted 1.10 is read as a float, and 1.10 and 1.1 are the same number, so the pin is written back as 1.1. This is not a 1.1 versus 1.2 difference: parsers on both versions do it. Version strings such as 1.2.3 contain two dots, are not valid numbers, and survive untouched, which is why only some entries in the same file break. Quote every version string and the problem disappears.
Quote it. Single and double quotes both force a string: double quotes process backslash escapes such as \n, single quotes take the text literally and escape an internal quote by doubling it, as in 'it''s'. To be explicit you can tag the value instead, and !!str 1.10 loads as the string 1.10. The same fix covers the boolean, leading-zero and float traps, and the date trap, where an unquoted 2026-08-09 loads as a date object rather than text.
No. JSON has no comment syntax, so comments cannot be represented and are dropped on the YAML to JSON leg. Anchors and aliases lose their sharing and reappear as repeated values, and a self-referencing anchor has no JSON form at all. A multi-document stream separated by --- has no single JSON equivalent either, so it needs an array or one file per document. Keep the YAML as the source of truth when the comments carry meaning.