How the conversion works
The JSON is parsed with JSON.parse and then walked recursively by a short converter script on this page (no third-party library). The mapping rules are simple and fixed:
- Each object key becomes a child element, in the order the keys appear.
- Strings, numbers and booleans become the element's text. The characters
&, <, > and " are escaped as entities.
null becomes a self-closing element.
- An array repeats its key once per item, with no wrapper element.
- If the top-level value is an array, each entry is wrapped in
<item> inside the root element. A top-level object's keys become the root's children, and a lone value such as 42 becomes <root>42</root>.
The root name comes from the text box in the toolbar (default root) and is cleaned up with the same rules as keys. You can choose 2 or 4 spaces of indentation or Minify for a single line, and switch the <?xml version="1.0" encoding="UTF-8"?> declaration on or off. Download saves the result as data.xml.
Example: an order payload
{
"order": {
"id": "A-1042",
"status": "shipped",
"customer": { "name": "Ada Lovelace", "email": "[email protected]" },
"items": [
{ "sku": "KB-01", "qty": 1, "price": 49.5 },
{ "sku": "MS-02", "qty": 2, "price": 25 }
],
"notes": "Fragile & heavy <box>",
"gift": false,
"coupon": null
}
}
With the defaults (root root, 2 spaces, declaration on):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<order>
<id>A-1042</id>
<status>shipped</status>
<customer>
<name>Ada Lovelace</name>
<email>[email protected]</email>
</customer>
<items>
<sku>KB-01</sku>
<qty>1</qty>
<price>49.5</price>
</items>
<items>
<sku>MS-02</sku>
<qty>2</qty>
<price>25</price>
</items>
<notes>Fragile & heavy <box></notes>
<gift>false</gift>
<coupon/>
</order>
</root>
Arrays need the most attention
JSON arrays have no direct equivalent in XML, and three consequences follow from the "repeat the key" rule:
- No wrapper element. The two order lines above appear as sibling
<items> elements. Many XML schemas expect <items><item>...</item></items> instead. To get that, nest the array one level deeper before converting: "items": {"item": [ ... ]}.
- Nested arrays are flattened.
{"matrix": [[1, 2], [3]]} produces three <matrix> elements, and the grouping into rows is lost. Wrap each inner array in an object, for example [{"cell": [1, 2]}, {"cell": [3]}].
- A one-item array looks like a plain value.
{"tags": ["urgent"]} and {"tags": "urgent"} both give <tags>urgent</tags>, so anything that reads the XML back cannot tell there was a list.
No attributes: everything is an element
The converter never writes attributes. Keys starting with @ or named #text, which some libraries treat specially, are ordinary keys here: "@id" becomes <_id> and "#text" becomes <_text>. If the receiving system needs <order id="A-1042">, edit the output by hand.
How key names are changed
- Any character outside ASCII letters, digits,
., _, - and : becomes an underscore: "first name" gives <first_name>.
- Names starting with a digit, dot or hyphen get a leading underscore:
"2fa" gives <_2fa>.
- Accented letters are replaced too, even though XML allows them:
"prénom" gives <pr_nom>.
- An empty key becomes
<item>.
- Colons are kept, so
"ns:tag" stays <ns:tag>. Without a matching namespace declaration, namespace-aware parsers will reject it.
Types and empty values are lost
XML text has no types: 49.5 and "49.5", true and "true" come out identical, so anything converting back has to guess. null, [] and {} all produce <key/>, while an empty string gives <key></key>. Control characters (other than tab and line breaks) are not removed, and they make the XML invalid.
When to use a different tool
- To check the result is well-formed, paste it into the XML Validator.
- To re-indent XML you edited by hand, use the XML Formatter.
- To convert XML back into JSON, use XML to JSON.
- If the target is a configuration file rather than a data exchange format, JSON to YAML is usually the better fit.
Frequently asked questions
How are arrays represented in the XML output?
Each array item becomes a repeated element named after the array key, with no wrapper element around the group. For example, {"items": [1, 2]} becomes <items>1</items><items>2</items>. If your schema expects a wrapper such as <items><item>1</item></items>, change the JSON to {"items": {"item": [1, 2]}} before converting.
What happens to JSON keys that are not valid XML element names?
Characters other than ASCII letters, digits, dot, hyphen, underscore and colon are replaced with an underscore, and a name that starts with a digit, dot or hyphen gets an underscore in front. So "first name" becomes first_name and "2fa" becomes _2fa. An empty key becomes item.
Can the converter create XML attributes?
No. Every key becomes a child element. Keys such as "@id" or "#text", which some converters treat as attributes or text nodes, are handled like any other key and become <_id> and <_text>. Add attributes to the output by hand if your target format needs them.
How are null, empty arrays and empty objects converted?
All three become a self-closing element such as <coupon/>. An empty string becomes an open and close pair with nothing inside, <coupon></coupon>. The difference between these cases is lost in the XML.
Why does my output contain <item> elements?
When the top-level JSON value is an array, each entry is wrapped in an <item> element inside the root element, because the array itself has no key to use as a name. Set the root name to something descriptive such as users to get <users><item>...</item></users>.
Is anything sent to a server?
No. The conversion is a small script that runs in your browser, with no server call and no external conversion library. Import URL fetches the file directly from your browser.