JSON to XML with predictable element names
This JSON to XML converter is for the moment your data is in JSON but the receiving end speaks XML: a SOAP endpoint, a payment gateway, an import screen in an ERP, or a test fixture for an XML parser. Objects become elements, arrays become repeated elements, and a small naming convention lets you produce attributes and mixed content too.
JSON and XML do not map one to one. JSON has arrays and typed values; XML has attributes, element order and a single document root. The rules below explain every decision the converter makes, so the result is not a surprise.
Example: an object with attributes and a list
{
"product": {
"@sku": "TX-40",
"name": "Desk lamp",
"price": { "@currency": "USD", "#text": 39.9 },
"colors": ["black", "white"],
"2nd warranty": null
}
}
Converted with the default options:
<?xml version="1.0" encoding="UTF-8"?>
<product sku="TX-40">
<name>Desk lamp</name>
<price currency="USD">39.9</price>
<colors>black</colors>
<colors>white</colors>
<_2nd_warranty/>
</product>
Four rules are visible here. The single top-level key product became the document element, so no extra <root> wrapper was added. Keys starting with @ turned into attributes. The #text key supplied the text of <price>. And the list of colors was written as two sibling elements that share the key's name.
How JSON structures become XML
| JSON | XML result |
|---|---|
| Object key with a scalar value | Child element containing the value as text |
| Key starting with the attribute prefix | Attribute on the parent element |
#text key | Text content of the parent element |
| Array under a key | One element per entry, each named after the key |
| Array inside an array | Entries wrapped in the Array item element name |
| Top-level array | Root element holding one item element per entry |
null, empty string, empty object | Self-closing element such as <note/> |
| Numbers and booleans | Plain text: true, 39.9 |
When does the Root element setting apply? Whenever the JSON is not a single-key object: a top-level array, an object with several keys, a bare value, or a single key whose value is an array. For example, {"users": [ … ]} produces <root> with repeated <users> children, because XML allows only one document element and an array would otherwise create several.
Options
- Root element – the wrapper name,
rootby default. Use the name the receiving schema expects, such asordersorEnvelope. - Array item element – the name for entries of a top-level array and of nested arrays,
itemby default. Converting[1, 2]with rootnumbersand itemngives<numbers><n>1</n><n>2</n></numbers>. - Attribute prefix – which key prefix marks an attribute. Keep
@for data produced by the XML to JSON converter, or change it (for example to_) if your keys legitimately begin with@. - XML declaration – prepends
<?xml version="1.0" encoding="UTF-8"?>. Untick it when the fragment will be pasted inside another document. - Indent – 2, 3 or 4 spaces, or a tab.
Names and characters that XML rejects
A JSON key can be any string, but an XML element name cannot contain spaces, cannot start with a digit and should not start with the letters "xml". Rather than emit a document that fails to parse, the converter rewrites such names: characters outside letters, digits, _ . : - become underscores, and an underscore is put in front of names that begin with a digit or with "xml". That is how 2nd warranty became _2nd_warranty. The same cleanup applies to the root and item names you type in the options.
Text values are escaped, so "a < b & c" is written as a < b & c. You never need to pre-escape anything in the JSON.
Common problems
- The JSON does not parse. The status bar shows the reason and position, for example
Trailing comma before '}' is not allowed (line 1, column 8). Fix it in the editor or run it through the JSON formatter first. - Element order matters to a schema. Elements follow the key order of your JSON objects, so reorder the keys in the input if an XSD requires a sequence.
- Namespaces. Prefixed element names such as
soap:Bodyare kept, because the colon is allowed. Namespace declarations work too: an"@xmlns:soap"key becomes anxmlns:soap="…"attribute on its element, andxml:langis kept as written.
After converting, paste the result into the XML validator if you want a second check before sending it to another system.
Privacy
The conversion runs in your browser; the JSON is not uploaded. Our server is only contacted when you use Load URL (the file is fetched through it) or Save & Share (the input is stored to create the link).
Convert JSON to XML in Python
The standard library has no single function for this, but xml.etree.ElementTree reduces it to a short recursive helper: a dictionary becomes child elements, a list repeats the element once per item, and anything else becomes text. Build the tree instead of concatenating strings, because ElementTree escapes & and < for you. It does not check element names, though: a JSON key with a space, such as "bad key", is written as <bad key>, which is not well-formed XML, so clean the keys first.
import json
import xml.etree.ElementTree as ET
def fill(element, value):
if isinstance(value, dict):
for key, item in value.items():
# a JSON array repeats the element once per item
for one in item if isinstance(item, list) else [item]:
fill(ET.SubElement(element, key), one)
else:
element.text = value if isinstance(value, str) else json.dumps(value)
data = json.loads('{"user": {"name": "Ann", "age": 30, "tags": ["a", "b"], "note": "R&D <lead>"}}')
root = ET.Element("user")
fill(root, data["user"])
ET.indent(root)
print(ET.tostring(root, encoding="unicode"))
The converter above replaces such characters with underscores, which makes it a handy reference for your script's output.