How to convert XML to JSON
- Drop an
.xmlfile into the box above, or paste the markup straight into the XML field. Nothing is uploaded either way. - Leave Keep repeating elements as arrays ticked unless you specifically want the old count-based behaviour.
- If you know an element that will repeat in your next file but happens to appear once in this one, type its name into the arrays field.
- Press Convert to JSON and read the report before you copy the result. It names what the conversion could not carry across.
The problem this page exists for
XML has no way to mark a list. A purchase order with three line items and a purchase order with one line item are both perfectly valid, and they look the same to a parser except for how many times the element occurs. So a converter guesses from the count:
| The XML | What converters give you |
|---|---|
<items><item>A</item><item>B</item></items> |
{"items": {"item": ["A", "B"]}} — an array |
<items><item>A</item></items> |
{"items": {"item": "A"}} — a string |
Both outputs are defensible and the second one is a bug waiting for a quiet Tuesday.
Code written against the first calls .item.map(), works for months, and
then throws the day an order arrives with a single line. Nothing changed in the feed;
the converter simply described the same structure two different ways.
Every converter we looked at documents this behaviour. None of them fixes it. Here, an element that repeats anywhere in the document is a list everywhere in the output, including under the parents where it occurs once — and if you know the shape of the data better than this particular file does, you can name the elements that must always be arrays.
Shape changes that are visible in one file
Sometimes the instability is provable without seeing a second file. If a document has one shelf holding two books and another shelf holding one, a count-based converter emits an array in the first and an object in the second — for the same element, in the same file. The report calls those out by name, because they are the clearest evidence that the output shape is an accident of the data rather than a property of the format.
What JSON cannot hold, and what we do about it
| In the XML | What usually happens | What happens here |
|---|---|---|
| An attribute and a child element with the same name | Without a prefix one overwrites the other and a field vanishes | Attributes are prefixed with @; the clash is named in the report |
| Two namespaces using the same local name | Prefixes stripped, two different elements merged into one key | Prefixes kept by default; if you strip them, every merge is listed |
| Text and child elements in the same element | The text is silently dropped | Kept under #text, and the paths are listed |
| Comments and processing instructions | Dropped without mention | Dropped — JSON has no equivalent — but counted |
<![CDATA[...]]> |
Usually fine, occasionally kept as a nested wrapper | Unwrapped to plain text, with the markup characters intact |
Numbers are where data goes missing
XML values are all text, so converting them to JSON numbers is a decision rather than a translation. Two cases cost real data and neither announces itself:
- Leading zeros.
00721is a postcode, not the number 721. Convert it and the zeros are gone permanently. - Long whole numbers. JavaScript holds integers exactly only up to
9,007,199,254,740,991. Past that — most 17-digit order, account and barcode
numbers — conversion changes the final digits:
9007199254740993becomes9007199254740992.
Both stay as text, and the page counts how many values were held back for that reason. You can also switch type conversion off entirely and receive every value as a string, which is what you want when the JSON is going straight into something that will parse it again.
Why a broken file gets an error rather than a result
XML is strict on purpose: an unclosed tag or a bare & makes a
document not well-formed, and the specification says a parser must stop. This page
uses the browser's own DOMParser, so it stops too, and shows the line and
column where it gave up. Tools that promise to convert “even if your XML is not
well-formed” are guessing at where the document should have ended — they
return something that looks complete and is missing everything after the fault.
Next steps
Going back the other way is JSON to XML, which reads the
@ prefix as attributes so a round trip keeps them where they belong. If
the XML is really a table, XML to CSV turns it into rows and
columns and tells you which element it treated as a record. And once you have JSON,
JSON to CSV flattens it into a spreadsheet. The rest are on
the data tools page.