JSON to YAML and YAML to JSON

Convert in either direction and see exactly where YAML quietly changes your data: NO becoming false, 1.10 becoming 1.1, 02134 becoming a number, dates, anchors and merge keys. Choose YAML 1.2 or 1.1 reading rules, get line and column for every syntax error, and nothing leaves your browser.

Load an example

    Runs in your browser with the open-source yaml package (version 2.9.1, ISC licence). Nothing is uploaded or stored. The share link puts your text after the # in the address, which browsers do not send to servers, but anyone you give the link to can read it: do not share configuration that contains secrets.

    How to use

    1. Pick the direction. YAML to JSON reads your YAML with the rules you choose (YAML 1.2 is the current specification; YAML 1.1 is what several older libraries still implement) and writes JSON.
    2. Read the table What the parser decided about your values. It lists every plain value that was turned into a number, that changed its text on the way, or that a parser of the other YAML version would read differently. Quote those values in your source if the text matters.
    3. Check the notes above the output: they say when documents were joined into an array, aliases expanded, comments dropped, or infinity written as null.
    4. For JSON to YAML paste strict JSON. Errors give the line and column. The output is parsed again and compared with your input, and the result of that check is shown under the output.
    5. Use Use output as input to flip a result back and compare. Use Load an example to see each gotcha on the sample text from this page.

    Worked examples

    Each block is a real input with the exact compact JSON the tool prints under YAML 1.2 and under YAML 1.1. The expected values were derived by hand from the YAML 1.2.2 core schema table and the yaml.org YAML 1.1 type pages, and a unit test runs every one of them through the converter.

    Core schema pattern (YAML 1.2.2, section 10.3.2)Read as
    null, Null, NULL, ~, or emptynull
    true, True, TRUE, false, False, FALSEboolean
    [-+]? [0-9]+integer, decimal (so 010 is 10)
    0o [0-7]+integer, octal (0o10 is 8)
    0x [0-9a-fA-F]+integer, hexadecimal (0x3A is 58)
    [-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )?floating-point number
    .inf, -.Inf, .NaN and spelling variantsinfinity, not a number
    anything elsestring

    A quoted scalar ("..." or '...') is always a string, and a tag such as !!str forces the type.

    The Norway problem: a country code becomes false

    countries:
      - GB
      - NO
      - SE
    Read asJSON the tool prints
    YAML 1.2 (default){"countries":["GB","NO","SE"]}
    YAML 1.1{"countries":["GB",false,"SE"]}

    The YAML 1.1 boolean type (yaml.org/type/bool) lists y, Y, yes, Yes, YES, n, N, no, No, NO, on, On, ON, off, Off and OFF as booleans, so the unquoted country code NO is false. YAML 1.2 dropped all of these; only true, True, TRUE, false, False and FALSE are booleans. Many tools, and the YAML parsers of several languages, still apply the 1.1 rules, so quote anything that could be read as one: "NO".

    The key on becomes true

    on:
      push:
        branches: [main]
    Read asJSON the tool prints
    YAML 1.2 (default){"on":{"push":{"branches":["main"]}}}
    YAML 1.1{"true":{"push":{"branches":["main"]}}}

    The same rule applies to keys, not only values. A YAML 1.1 parser reads the key on as the boolean true, and JSON then has to write it as the member name "true". Anything that reads such a file as YAML 1.1 and looks for a key named on will not find it.

    A leading zero: 02134 is 2134 or 1116

    zip: 02134
    Read asJSON the tool prints
    YAML 1.2 (default){"zip":2134}
    YAML 1.1{"zip":1116}

    The YAML 1.2 core schema reads [-+]?[0-9]+ as a decimal integer, so the leading zero is lost and the zip code is the number 2134. YAML 1.1 reads a leading 0 as octal: 2*8^3 + 1*8^2 + 3*8 + 4 = 1024 + 64 + 24 + 4 = 1116. Zip codes, phone numbers and IDs with leading zeros must be quoted. A value such as 08 is not valid octal, so YAML 1.1 falls back to decimal 8 (observed with the yaml package; the 1.1 spec does not describe it).

    A version number loses its trailing zero

    python: 3.10
    node: 20.10
    Read asJSON the tool prints
    YAML 1.2 (default){"python":3.1,"node":20.1}
    YAML 1.1{"python":3.1,"node":20.1}

    Both versions read 3.10 as a floating-point number (the core schema float pattern is [-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )?), and a number carries no trailing zero, so JSON gets 3.1. The text "3.10" and the number 3.1 are different values; a CI matrix that asks for Python 3.10 and gets 3.1 is the classic result. Quote versions: "3.10".

    A time such as 12:30 is a number in YAML 1.1

    at: 12:30
    Read asJSON the tool prints
    YAML 1.2 (default){"at":"12:30"}
    YAML 1.1{"at":750}

    YAML 1.1 allows base-60 integers written with colons (yaml.org/type/int: [-+]?[1-9][0-9_]*(:[0-5]?[0-9])+). 12:30 is 12*60 + 30 = 750. YAML 1.2 removed this, so the text stays a string. The same happens to 190:20:30, which is 190*3600 + 20*60 + 30 = 685230.

    A date is text in YAML 1.2 and a timestamp in YAML 1.1

    released: 2001-12-14
    Read asJSON the tool prints
    YAML 1.2 (default){"released":"2001-12-14"}
    YAML 1.1{"released":"2001-12-14T00:00:00.000Z"}

    The YAML 1.1 timestamp type (yaml.org/type/timestamp) treats a plain date as a timestamp at 00:00:00 UTC. JSON has no date type, so this tool writes the ISO 8601 string. A parser that builds real date objects will hand your code a Date, not the text you wrote.

    An empty value is null, not an empty string

    name:
    nickname: ~
    motto: ""
    Read asJSON the tool prints
    YAML 1.2 (default){"name":null,"nickname":null,"motto":""}
    YAML 1.1{"name":null,"nickname":null,"motto":""}

    The core schema resolves an empty plain scalar, ~, null, Null and NULL to null. Only the pair of quotes gives an empty string. A config key left blank is therefore null.

    The merge key << merges only under YAML 1.1 rules

    base: &b {x: 1}
    d:
      <<: *b
      y: 2
    Read asJSON the tool prints
    YAML 1.2 (default){"base":{"x":1},"d":{"<<":{"x":1},"y":2}}
    YAML 1.1{"base":{"x":1},"d":{"x":1,"true":2}}

    The merge key is defined on yaml.org/type/merge for YAML 1.1 and does not appear in the YAML 1.2.2 specification. With the default settings here << is an ordinary key, so nothing is merged (many libraries merge it anyway; behaviour varies). Tick "Treat << as a merge key" to merge. The 1.1 result above also shows the key y turning into "true": the two gotchas combine.

    Several documents in one file

    name: first
    ---
    name: second
    ---
    - third

    Output: [{"name":"first"},{"name":"second"},["third"]], with the note that JSON has no multi-document form.

    What goes wrong

    Syntax errors a converter should explain rather than guess around. The messages are the parser's own; the tool adds the line and column and shows the offending line.

    A tab used as indentation

    a:
    <TAB>b: 1

    Error: Line 2, column 1: Tabs are not allowed as indentation

    YAML 1.2.2 section 6.1 says tab characters must not be used in indentation. Editors that insert tabs are the usual cause; use spaces.

    Duplicate keys

    a: 1
    a: 2

    Error: Line 2, column 1: Map keys must be unique

    YAML requires the keys of a mapping to be unique (YAML 1.2.2 section 3.2.1.1). Many parsers silently keep the last value; this one stops and tells you where. JSON is different: RFC 8259 calls duplicate names "unpredictable".

    An unclosed flow list

    server:
      host: example.com
      ports: [80, 443
      tls: true

    Error: Line 4, column 3: Flow sequence in block collection must be sufficiently indented and end with a ]

    The position is where the parser gave up: it was still looking for the closing bracket when the next line (tls: true, line 4) began. It is not where the list started, and the real mistake is on the line above the reported one.

    Alias without an anchor

    a: &x 1
    b: *x
    c: *y

    Error: Line 3, column 4: The alias *y has no anchor. An anchor (&y) must be written earlier in the same document.

    YAML 1.2.2 section 3.3.1 requires each alias to refer to a previous node identified by the anchor, and says a processor should reject unidentified aliases.

    Keys that JSON cannot hold

    1: a
    "1": b

    Error: Two mapping keys both become the JSON member name "1" (for example 1 and "1"). JSON would then have a duplicate name, so the conversion stops.

    YAML keys can be numbers, booleans, null or even whole lists; JSON member names are strings. A key that is a list or map cannot be converted at all, and the tool says so.

    Trailing comma in JSON

    {
      "a": 1,
    }

    Error (JSON to YAML): Line 3, column 1: Trailing comma before "}", with the hint "JSON does not allow a comma after the last member." JSON (RFC 8259) does not allow a trailing comma, comments or single quotes, although YAML does allow comments.

    Limits & gotchas

    • The behaviour for YAML 1.1 is that of one library, not the specification. The yaml package implements 1.1 as an option. The booleans, octal, hexadecimal, binary, underscores, base-60 integers and timestamps shown here match the yaml.org 1.1 type pages in the cases tested; where those pages are silent (for example 08, which is not valid octal) the tool reports what the library does and says so. Other libraries differ, which is the point of the gotchas above.
    • The 1.2 default is the core schema. The YAML 1.2.2 specification recommends the core schema as the default for processors, and that is what "YAML 1.2" means here. Other schemas (failsafe, JSON) and custom tags are not offered. Unknown tags are ignored with the value kept as text; !!binary is written as Base64 and timestamps as ISO 8601 strings.
    • Merge keys. << is merged only when you tick the option or choose YAML 1.1. The YAML 1.2.2 text does not define it, and libraries disagree on whether to merge by default.
    • A %YAML directive in your text wins. If a document starts with %YAML 1.1, the library reads it as 1.1 whatever the selector says; the tool prints a note when it sees one. This was observed, not taken from a specification.
    • Comments, anchors and formatting are not round-tripped. Output is regenerated, so comments, anchor names, quoting style and blank lines from the source are not preserved. Long lines are not folded.
    • Numbers. Integers beyond 253-1 are written exactly in the JSON, but JavaScript's JSON.parse will round them when your code reads the file. Infinity and NaN cannot be written in JSON and become null, with a note.
    • Mapping key order for whole-number keys in JSON to YAML follows JavaScript object order (integer-like names first, ascending), because the JSON is read into a JavaScript object. The tool says when this applies.
    • Size. No hard limit; the page converts on every pause in typing, so very large documents (many megabytes) will feel slow. The alias limit of 100 stops expansion bombs.
    • Share links carry your text in the part after #, up to about 3,000 characters. Never share configuration that contains passwords, tokens or keys.

    Library: the yaml npm package by Eemeli Aro, version 2.9.1, ISC licence (a permissive licence); the licence and version were read from the package metadata installed with this site.

    FAQ

    Why did NO (or no, yes, on, off) turn into a boolean?

    Because the parser follows YAML 1.1, whose boolean type includes y, Y, yes, Yes, YES, n, N, no, No, NO, on, On, ON, off, Off and OFF (yaml.org/type/bool). YAML 1.2.2 (core schema) only treats true, True, TRUE, false, False and FALSE as booleans, so under 1.2 the country code NO is the string "NO". Which one you get depends on the library. If a value must stay text, quote it, and use the "Read YAML as" selector above to see both results.

    Does the converter keep comments, anchors and key order?

    Key order is kept for YAML to JSON. Comments are not part of the data and are dropped; the tool tells you when it drops any. Anchors and aliases are expanded into full copies, because JSON has no references, and the output says how many it expanded. JSON to YAML cannot recreate anchors or comments that the JSON never had. One exception to key order: JSON member names that are whole numbers (such as "2") are listed first in ascending order, because JavaScript objects order them that way, and the tool says so when it happens.

    What happens to a file with several documents separated by ---?

    YAML allows many documents in one stream (YAML 1.2.2 chapter 9); JSON does not. The converter writes the documents as one JSON array, in order, and says so. A file with a single document is not wrapped. If you need one JSON file per document, split the stream at the --- lines first.

    Is the converter safe for huge or hostile YAML?

    It runs in your tab, so nothing reaches a server, but a malicious document can still try to use your memory. The parser stops after its alias limit (maxAliasCount 100 in the yaml package) to defeat "billion laughs" documents that expand exponentially, and the tool reports it as an error. There is no other size limit besides the memory of your browser, and very large inputs make typing slow.

    Will JSON converted to YAML read back identically?

    The tool checks this for you: after writing YAML it parses the result again and compares it with your JSON, and shows a warning if they differ. Strings that would otherwise be read as another type (true, null, 010, 1.10, ~, an empty string, text containing ": ") are quoted. Words such as NO, y or 12:30 are only quoted if you tick the YAML 1.1 option, because under YAML 1.2 they are plain strings. Numbers beyond 2^53 are written exactly, but JavaScript's JSON.parse rounds them when reading.

    Sources

    Every document above was opened and read on 2026-10-02. Documentation changes; if a page here disagrees with the current docs, trust the docs and tell us.