Free online JSON to XML converter
JSON to XML with the losses spelled out
This JSON to XML converter is free, takes no signup and works entirely in the browser on payloads up to 5 MB. You name the root element, choose whether an array repeats its key or wraps its items in a container, and decide what null becomes — the three places where JSON has a construct XML does not. Every key that could not legally be an element name is renamed and listed underneath with its original spelling, so nothing changes quietly on the way across.
- 100% free
- No signup
- Up to 5 MB
- Root and item names
- Renames listed
The XML appears here as you type.
Paste JSON, open a file, or press Ctrl+V anywhere on this page.
The empty array that leaves no trace
Repeating the key is the idiomatic way to write a list in XML and the reason a round trip is not safe. Watch what happens to three payloads that differ in a way the markup cannot express.
No tags at all
{ "id": 1, "tags": [] }becomes
<root> <id>1</id> </root>
One tag
{ "id": 1, "tags": ["new"] }becomes
<root> <id>1</id> <tags>new</tags> </root>
A plain string
{ "id": 1, "tags": "new" }becomes
<root> <id>1</id> <tags>new</tags> </root>
The second and third payloads produce identical markup, and the first loses the key entirely — three distinguishable JSON values, two XML documents. Wrapping arrays in a container fixes the first case, giving <tags/>, and the second at the cost of an extra <item> level. Nothing fixes all three without a schema.
How to convert JSON to XML
Three steps: paste the payload, name the root and the array style, read the renames.
Paste the payload and name the root
XML permits exactly one top-level element and JSON permits an array, a number or a bare string, so the first thing to decide is the root: call it order, response, or whatever the schema on the other side expects. Type it in the box, then paste the payload — the editor accepts a keyboard paste wherever you are on the page, or a .json file up to 5 MB.
Decide what an array looks like
Repeating the key writes <line>…</line><line>…</line> with no container, which is how most XML vocabularies model a list. Wrapping puts the items inside a parent as <lines><item>…</item></lines> instead. Pick the prefix that turns a key into an attribute — @id by default — and choose whether null becomes an empty element, an xsi:nil="true" element, or nothing at all.
Check the renames, then copy
The bar underneath lists every key that could not be an element name and what it became: 2fast → <_2fast>, "with space" → <with_space>. With the name attribute switched on, each renamed element carries its original key so the mapping stays recoverable. The Copy button lifts the markup as it stands; Download writes an .xml file named after your root element.
Technical specifications
| Accepted input | Any RFC 8259 document — object, array, string, number, true, false or null at the top level; number literals of any length are copied through as written |
|---|---|
| Root element | Required and configurable (default root); XML permits exactly one top-level element, so a top-level array is always wrapped |
| Array styles | Repeat the key per item, or wrap items in a named element (default item) — the first loses empty arrays, the second adds a container |
| Attributes | Keys prefixed @, @_ or $ become attributes when their value is a scalar; set the prefix to nothing and everything becomes an element |
| null styles | <key/>, <key xsi:nil="true"/>, or the element omitted — 3 options, counted in the report |
| Key renaming | Characters outside the XML Name production become _, a leading digit or dot gains a leading _, and the original key is kept in a name attribute |
| Characters dropped | U+0000–U+0008, U+000B, U+000C, U+000E–U+001F, U+FFFE and U+FFFF — outside the XML 1.0 Char production and unrepresentable even as &#NN; |
| Output and speed | 2-space, 4-space or single-line, with an optional <?xml version="1.0" encoding="UTF-8"?> declaration; &, < and > escaped in text, plus " and newlines in attribute values. 12,000 records of 2.83 MB became 132,001 elements and 3.35 MB of XML in 0.06 seconds. 5 MB per payload and 500 levels of nesting are the ceilings; free, no signup, converted in this browser tab |
Frequently asked questions
How do you write a JSON array in XML?
Two ways, and neither is a sequence: XML has repetition instead. Repeating the key gives <tag>a</tag><tag>b</tag>, which matches how RSS, SOAP and most industry schemas model lists, but the array boundary is gone — nothing says where the list starts and ends except that the elements are adjacent. Wrapping gives <tags><item>a</item><item>b</item></tags>, which keeps the boundary and adds a container element that was never in your data.
What happens to an empty array?
It disappears entirely when the key is repeated, because zero items means zero elements and the key leaves no trace at all. {"tags": []} and {} produce byte-identical XML in that mode, so a consumer cannot tell "the customer has no tags" from "tags were not sent" — the distinction your API may care about is destroyed. Wrapping in a parent keeps <tags/>, which at least survives, though it reads back as null rather than as an empty list.
How is null represented in XML?
XML has no null, so you pick one of three lies. An empty element <coupon/> is the common choice and is indistinguishable from an empty string. xsi:nil="true" is the schema-aware option defined by XML Schema Part 1 and is understood by anything built on XSD, at the cost of requiring the xsi namespace to be declared. Omitting the element altogether is the third, and it turns a null into an absent field.
What if a JSON key is not a valid XML element name?
It is renamed, and the original is kept as a name attribute unless you turn that off. XML 1.0 names cannot start with a digit, cannot contain spaces, slashes, colons used loosely or most punctuation, so keys like 2fast, order id and user.name@v2 have no direct equivalent — invalid characters become underscores and a leading digit gains an underscore in front. Keys beginning with the letters xml are technically reserved by the specification but are emitted unchanged, because every parser in practice accepts them.
Can XML carry every character that a JSON string can?
No, and this is the one loss that cannot be escaped around. JSON strings may contain any code point, including U+0000 to U+0008, U+000B, U+000C and U+000E to U+001F; the XML 1.0 Char production excludes those outright, and a numeric reference does not help — � is as illegal as the raw byte. Control characters are therefore removed and counted, which matters if you are moving base64-adjacent data or the output of a binary protocol.
Do numbers and booleans stay typed in XML?
No. Every value becomes character data, so 8080, "8080" and true are all just text between tags, and only a schema or an explicit annotation can tell them apart afterwards. Switching on the type attributes writes type="number" and type="boolean" on the affected elements — that is a convention, not a standard, though it survives a round trip back here and is far cheaper than shipping an XSD alongside.
Which JSON keys become XML attributes?
Keys starting with the prefix you choose — @ by default, so {"@id": "A-4417"} becomes id="A-4417" on the parent element. The convention mirrors what XML-to-JSON converters produce, which makes a round trip between the two possible. Set the prefix to “nothing” and every key becomes an element instead, and an object whose value is not a scalar is always written as an element regardless of its prefix, because an attribute can only hold text.
About writing JSON as XML
JSON has four things XML has no direct home for, and knowing which one you are hitting explains most of what a converter does to your data. The first is the array: XML models a list as a repeated element, so the brackets vanish and with them the difference between an empty list and a missing field. The second is null, which XML Schema addresses with an xsi:nil attribute rather than a value, meaning a plain document has to choose between an empty element and silence. The third is the key itself — an XML Name cannot start with a digit or hold a space, so any payload built from user input or database columns will have keys that need rewriting. The fourth is type: everything in XML is text until a schema says otherwise, so 8080 and "8080" leave here spelled the same.
The character range is the loss people meet last and understand least. XML 1.0 defines which code points may appear in a document at all, and the C0 control characters other than tab, carriage return and line feed are excluded from that set — not merely inconvenient to write, but forbidden, with no escape available. A JSON string carrying a form feed or a NUL simply cannot be transported as XML text, so those characters are dropped here and counted in the report rather than producing a document that no parser will read back. That is worth checking before you send anything downstream: run the output through the XML validator if the payload came from somewhere you do not control.
None of this makes the conversion useless — it makes the round trip untrustworthy. Sending JSON into a SOAP endpoint, an RSS pipeline or an XSLT transform is a one-way job, and for that the output here is exactly what those consumers expect. What you should not assume is that pushing the result back through XML to JSON returns the document you started with; arrays of one, empty arrays and nulls all come back changed. If the payload is only being read rather than transported, the JSON viewer spares you the conversion altogether.
What happens to the payload
Nothing you paste is uploaded. The JSON is parsed and the XML written by code that arrived with this page, so order numbers and personal data stay on your machine; close the tab and the payload goes with it.