Skip to content

XML to JSON converter

Convert XML to JSON and back, with explicit control over attributes and over the repeated-element problem that makes every other converter lossy.

XML distinguishes an attribute from a child element and JSON has no equivalent distinction, so this has to be a choice rather than a default.
The one genuinely lossy part of the conversion. A list of one item and a single item look identical in XML, so code written against a two-item file breaks on a one-item file.
JSON to XML only. XML needs exactly one root element and JSON does not have one, so a name has to come from somewhere.
Runs in your browser — nothing is sent anywhere.

The conversion is lossy, and pretending otherwise is the problem

XML and JSON can express different things. Any converter has to make choices, and most make them invisibly — which is fine until the output changes shape and something downstream breaks. So the three real choices are exposed here rather than buried.

Repeated elements: the one that causes outages

This is the important one. Consider two files:

<items><i>a</i></items>
<items><i>a</i><i>b</i></items>

A converter that emits an array when it sees two children and a plain value when it sees one gives you {"i": "a"} for the first and {"i": ["a","b"]} for the second. The JSON's shape depends on the data. Code written against a file that happened to have two items then fails the day a file arrives with one — at runtime, in production, on the customer's data rather than yours.

That is the default behaviour of nearly every XML-to-JSON converter, including this one's first option, because it produces the tidiest-looking output. If a program is going to read the result, choose always an array instead. The output is slightly uglier and its shape no longer depends on how many rows the file happened to contain.

Attributes

XML distinguishes <user id="1"/> from <user><id>1</id></user>. JSON has no such distinction, so a convention has to be invented. The usual one is an @ prefix, which is the default; grouping them under a single key keeps the object cleaner; discarding them is right when the attributes are only schema plumbing.

What happens to the xmlns declarations follows from the namespace setting, and the two answers are not arbitrary. Keep the prefixes and the declarations come with them — because a prefix is meaningless without its binding, and JSON converted back to XML would carry <soap:Envelope> with nothing declaring soap, which is not well-formed and will not reparse. Strip the prefixes and the declarations go too, because at that point you want the data rather than the document.

Mixed content

<p>Hello <b>world</b>!</p> interleaves text and elements in an order JSON cannot express. The text is gathered under $text and its position relative to the children is genuinely lost. You are told when this happens rather than left to find out.

Comments and processing instructions are dropped for the same reason — JSON has nowhere to put them, and inventing a place would be worse than losing them.

An XML file cannot make this read your files

XML has a feature called external entities, which lets a document ask its parser to go and fetch a file or a URL and paste the contents in. Feed a crafted document to a server-side XML parser with that switched on and it will read /etc/passwd for you, or make requests into a private network on your behalf. It is a well-known and still-common vulnerability class.

Because this runs in the browser, the parser doing the work is the browser's own, and it does not resolve external entities at all. A server-side converter has to remember to switch that off. This one cannot switch it on.

Going the other way

JSON to XML needs two things JSON does not have. First a root element, because XML requires exactly one and JSON has none — so a name is asked for. If your JSON already has a single top-level key, that is used instead, which means a file converted here and back comes out the same shape it went in.

Second, element names are far stricter than JSON keys: no spaces, no leading digit, and a short list of legal punctuation. A key that cannot legally be an element name is sanitised, and every rename is listed so nothing changes quietly.

Arrays become repeated elements of the same name, which is how XML expresses a list. Keys beginning with @ become attributes, matching the convention used in the other direction. An array at the very top is wrapped in the root element with each entry as an <item>, since XML permits exactly one root and emitting one element per entry would produce a document nothing will open.

01

Common questions

Why is a single-element list not an array?

Because XML cannot tell a one-item list from a single item — they are the same document. Choose "always an array" if code will read the output, or its shape will change with the data.

How are attributes handled?

By default with an @ prefix, so id="1" becomes "@id": "1". You can group them under one key or drop them. It has to be a choice because JSON has no attribute concept.

What happens to mixed text and elements?

The text goes under $text and its position among the children is lost — JSON cannot express the interleaving. It is reported when your file contains it.

Is it safe to paste XML from an untrusted source?

Safer here than in most places. The browser parser does not resolve external entities, which is the mechanism behind XXE attacks on server-side XML parsers.

Are namespaces preserved?

Prefixes are kept by default, along with the xmlns declarations that bind them — without those the XML would not reparse. Strip the prefixes and the declarations go too, but two namespaces sharing a local name will then collide.

Why does JSON to XML ask for a root name?

XML needs exactly one root element and JSON has none. If your JSON has a single top-level key that is used instead, so a round trip keeps its shape.

Is my XML uploaded?

No. It is parsed in this page, which is both why it is instant and why there is no size limit.