What the syntax converters do
JSON, YAML, XML, TOML and CSV do not hold the same things. This page states exactly how each shape is mapped, which conversions are lossy, and what the tool refuses to do.
What it converts
Nine directed conversions: JSON to YAML, YAML to JSON, JSON to XML, XML to JSON, JSON to TOML, TOML to JSON, YAML to TOML, TOML to YAML, and JSON to CSV. Every one runs in your browser tab; nothing is uploaded.
Each conversion works the same way internally: the source document is read into an ordinary JavaScript value, and that value is written out in the target format. YAML to TOML is not a special case, it is the YAML reader followed by the TOML writer. That is why the caveats below are stated per format rather than per pair — a caveat about TOML datetimes applies wherever TOML appears.
CSV is write-only, and deliberately so. Reading CSV means guessing a delimiter, a quoting dialect, whether the first row is a header, and a type for every cell — four guesses, each of which a converter gets wrong quietly. That is a job for a tool that asks.
XML: attributes, arrays and the rules we picked
XML has no canonical JSON mapping, so the conventions had to be chosen. They are visible on screen whenever XML is one of the two formats, and they are these.
Attributes become object keys prefixed with @. <user id="7"><name>Ada</name></user> reads as {"user":{"@id":"7","name":"Ada"}}. The prefix is what keeps an attribute and a child element of the same name from collapsing into one key — <user id="7"><id>other</id></user> keeps both.
Text inside an element that also has attributes or child elements lives under the key #text. An element containing nothing but text collapses to that text. A CDATA section lives under #cdata, so its contents are visibly data rather than markup.
Repeated sibling elements become an array. An element name that appears once does not become an array — XML gives a parser no way to tell "a list with one item" from "a single value", and no converter can invent that information. If you need a stable shape, that is an argument for a schema, not for a cleverer converter.
Namespace prefixes are kept verbatim: <ns:item> is the key ns:item and xmlns:ns is the attribute @xmlns:ns. Nothing is resolved, rewritten or stripped, because resolving a prefix throws away the text the document actually contained.
A self-closing tag reads as an empty string. The XML declaration, processing instructions and comments are dropped. Going the other way, the tool writes its own declaration and never a DOCTYPE.
Writing XML, a key that is not a legal XML element name — one with a space, one starting with a digit, one starting with the letters xml — is refused by name rather than silently rewritten. A quietly renamed element produces a document that validates against nothing.
External entities are refused, not merely disabled
An XML document may declare entities in a DOCTYPE. A parser that expands them is the XXE vulnerability: an entity declared SYSTEM "file:///etc/passwd" reads a local file, one pointing at a URL makes a request an attacker controls, and a chain of internal entities is the "billion laughs" denial of service that turns a few hundred bytes into gigabytes.
This converter does not configure a parser to be careful about DOCTYPEs. It refuses any document containing one, before the parser is given a single byte, with no option to turn the refusal off. That makes the guarantee a property of our code rather than of a dependency’s default setting — and the difference matters, because defaults change between versions and our own refusal is covered by tests that feed it every standard XXE payload and assert that nothing was fetched and nothing was expanded.
The practical cost: a document with a DOCTYPE will not convert here even when it is harmless. Delete the DOCTYPE if the content is yours.
TOML datetimes have no equivalent anywhere else
TOML 1.0 has four temporal types and JSON, YAML and XML have none: offset date-time (1979-05-27T07:32:00Z), local date-time (1979-05-27T07:32:00, with no zone, deliberately), local date (1979-05-27) and local time (07:32:00).
Each becomes the RFC 3339 string exactly as it was written, and the conversion tells you which values it did that to and which of the four kinds each one was. The alternative — emitting a single UTC instant for all four — would move a local time into a zone the document explicitly refused to state, which is a wrong answer rather than a lossy one.
Converting back produces quoted strings, not datetimes. A TOML to JSON to TOML round trip therefore changes the types of those values. There is no way around this without inventing a convention that the receiving tool would have to share, and inventing one silently would be worse.
TOML integers are signed 64-bit; JSON numbers are IEEE-754 doubles. An integer past 2^53 - 1 becomes a string, with the path named in a warning, rather than losing its last digits to a rounding you would not notice.
TOML has no null. A null key is omitted from the output and named in a warning; a null inside an array becomes an empty string, because removing it would shift every later index. A TOML document’s root is always a table, so an array or a bare value at the root is refused with a sentence saying why.
YAML: anchors, streams and the Norway problem
YAML is read with a restricted schema that can only produce strings, numbers, booleans, null, lists and maps. Tags that construct arbitrary objects — !!js/function, !!python/object/apply, !!binary — are refused, which is the whole reason the restriction exists: a loader that honours them is an arbitrary-object constructor wearing a config file’s clothes.
Anchors and aliases are resolved into repeated data. A document that expands past a million values once its aliases are followed is refused rather than allowed to freeze the tab; a recursive alias is refused outright, because no other format here can express a cycle.
A stream of several documents separated by --- becomes an array of documents, and the conversion says so. No other format in this tool has a stream, so an array is the only honest mapping.
YAML forbids a repeated mapping key, and every parser handles one differently. This tool keeps the last value — the rule JSON.parse uses — and tells you it happened, with the position of the repeat. Silently discarding a document would be worse; silently picking a value without saying so would be worse still.
The Norway problem: in YAML 1.1, the unquoted scalars y, yes, on, no, off and the country code NO all resolve to booleans, which is how a list of country codes turns into a list of trues and falses. This tool reads YAML 1.2, where only true and false are booleans, so NO stays the string NO. When it writes YAML it quotes every string a 1.1 parser would misread — 'NO', 'yes', 'on', '1.0', '0755', '2001-12-14' — so the output is safe to feed to a tool that has not moved to 1.2. That costs a few quote characters and buys correctness.
Strings that look like numbers keep their quotes for the same reason: "0755" stays a string rather than becoming 755, and "1.0" stays a string rather than becoming 1.
Comments are lost in every direction. JSON, CSV and the others have nowhere to put them, and there is no way to guess where they should go coming back.
JSON to CSV: flattening, and the apostrophe that stops a formula
An array becomes the rows, one record per element. An object whose single property holds an array uses that array as the rows, because {"users": [ ... ]} is overwhelmingly a table with a label — and the conversion says out loud that it did that. Any other object is a single row. A bare string, number or null is refused: a rectangle needs records.
Nested objects and arrays are flattened into dotted column names, with a dot for both object keys and array indices: address.city, tags.0, tags.1. One separator, one rule. A key that already contains a dot makes its column name ambiguous with a nested path; the tool warns rather than inventing an escaping scheme that no spreadsheet would understand.
Keys are unioned across every row, in first-seen order. A row missing a field gets an empty cell rather than a shifted column, and the conversion warns that the rows were ragged. An empty object or empty array becomes one empty cell under its own path rather than vanishing.
Quoting follows RFC 4180: a field containing the delimiter, a double quote, CR or LF is enclosed in double quotes and an embedded quote is written twice. Records are separated by CRLF. Fields with leading or trailing whitespace are quoted too, because spreadsheets silently trim them otherwise. Unicode passes through unchanged, and a byte-order mark can be prefixed for spreadsheets that need one to read UTF-8.
Formula injection is the one that bites. A cell beginning with =, +, -, @, a tab or a carriage return is executed as a formula by Excel, LibreOffice Calc and Google Sheets the moment the file is opened. =cmd|'/c calc'!A1 is the demonstration everyone quotes; =IMPORTXML(...) is the one that quietly sends the sheet somewhere. A converter that writes such a string verbatim has turned your data into someone else’s code execution, in a file that looks inert.
So a text cell starting with one of those characters is prefixed with an apostrophe, which every major spreadsheet reads as "this is text" and does not show in the cell. Numbers are left alone: a numeric -5 is a number, not a formula. The count of escaped cells is reported, and the escaping can be switched off — in which case the tool says plainly what you have just switched off.
CSV cannot tell an empty string from a null. Both become an empty cell, and the conversion counts the nulls so you know it happened.
Limits, and what happens when you hit one
Every format has a character cap, enforced before a parser is even downloaded: 8 million for JSON, 4 million for XML and for a CSV source, 2 million for YAML and TOML. Beyond that the tool refuses with the exact number, rather than becoming an unresponsive tab that loses what you pasted.
CSV output is additionally capped at 100,000 rows and 2,000 columns, because a deeply nested array flattens into one column per element and a few megabytes of JSON can become a table no spreadsheet will open.
Empty and whitespace-only input is reported as empty rather than converted into null or an empty document. Invalid syntax is reported with a line and a column in all four readable formats.
The parsers themselves are downloaded only when a conversion needs them. Opening the toolkit to decode a JWT fetches none of them.
What happens to what you paste
- Every conversion, hash, decode and diff runs in your browser tab. No input is uploaded, logged or stored on a server, because there is no server involved once the page has loaded.
- Hashes come from the browser’s own Web Crypto implementation, and UUIDs from its cryptographically secure random generator. Neither involves a network call.
- Nothing you type is written to local storage or a cookie. Reloading the page discards it; closing the tab discards it.
- There is no analytics script, no advertising script and no third-party request of any kind. You can confirm all of this in your browser’s network panel — the page makes no requests after it loads.
- That said: a JWT or an API key is a live credential. The safe habit is never to paste one into a web page you did not write, however trustworthy its claims — including this one.
Questions
Why does my XML document fail with "declares a DOCTYPE"?
Because it contains a document type declaration, and this converter refuses every one of them rather than trusting a parser setting to handle entities safely. Delete the DOCTYPE if the content is yours. There is no option to allow it.
Why did my TOML datetime come back as a quoted string?
Because JSON, YAML and XML have no date type. The datetime was converted to the RFC 3339 text it was written as, which is a string in every other format. Converting back therefore produces a string, and the tool warns you at the moment it happens rather than letting you find out later.
Why does one of my CSV cells start with an apostrophe?
Because its text begins with =, +, -, @, a tab or a carriage return, and a spreadsheet executes such a cell as a formula when the file is opened. The apostrophe marks the cell as text; it is not part of the value once the cell is read. You can switch the escaping off, and the tool will tell you what that means.
Why is a single repeated XML element not an array?
Because XML provides no way to distinguish a list of one from a single value. Both are written identically. Making the guess in either direction would be wrong half the time, so the tool reports what is actually there.
Can I convert CSV back into JSON here?
No. Reading CSV correctly requires deciding on a delimiter, a quoting dialect, whether the first row is a header and a type for every cell. A converter that guesses all four is wrong quietly, which is the worst way to be wrong. Use a CSV tool that asks.
Why is "NO" not converted to false?
Because that behaviour belongs to YAML 1.1 and this tool reads YAML 1.2, where only true and false are booleans. The 1.1 behaviour is the reason Norway’s country code is a running joke in configuration management. When the tool writes YAML it quotes such strings so no 1.1 parser downstream can misread them either.
Limitations
- CSV is written, never read. There is no CSV to JSON conversion here, by choice.
- Comments are lost in every direction, in every format that has them.
- A TOML datetime becomes a string in every other format, so a TOML round trip changes those types. There is no lossless path.
- An XML document containing a DOCTYPE is refused outright, including harmless ones, and the refusal cannot be switched off.
- A single repeated XML element cannot be distinguished from a non-repeated one, so XML to JSON to XML does not always return the original shape.
- XML mixed content — text interleaved with child elements — loses the position of the text relative to the children, and cannot round-trip.
- XML values are strings unless type inference is switched on, because XML declares no types; with inference on, "0755" and "NO" are subject to the usual misreadings.
- TOML has no null: null keys are dropped from TOML output and nulls inside arrays become empty strings.
- A TOML document’s root must be a table, so a JSON array or scalar cannot be converted to TOML at all.
- JSON numbers are IEEE-754 doubles. Integers past 2^53 are converted to strings rather than silently rounded, which changes their type.
- CSV cannot distinguish an empty string from a null; both are written as an empty cell.
- CSV flattening uses a dot for both object keys and array indices, so a key that already contains a dot produces an ambiguous column name that is warned about but not escaped.
- YAML anchors and aliases are resolved rather than preserved; the output has no anchors, and a recursive alias is refused because no target format can express a cycle.
- Input is capped per format — 8 million characters for JSON, 4 million for XML, 2 million for YAML and TOML — and oversized documents are refused rather than processed slowly.
- Nothing here validates against a schema. A document can convert cleanly and still be wrong for its purpose.
Last reviewed 2026-09-13.