Convert JSON to XML: Root Elements, Attributes, and Arrays
XML needs a single root and represents lists as repeated elements. Map @-prefixed keys to attributes and #text to element text for a reversible conversion.
Choosing a Root Element
XML 1.0 requires exactly one root element — the document's outermost open tag must match the document's outermost close tag. If the JSON has a single top-level key, use it as the root; otherwise wrap everything in a synthetic root element.
// JSON — has a single top-level key
{ "user": { "name": "Ada", "year": 1815 } }
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>Ada</name>
<year>1815</year>
</user>
// JSON — no single top-level key, so wrap
{ "name": "Ada", "year": 1815 }
<?xml version="1.0" encoding="UTF-8"?>
<root>
<name>Ada</name>
<year>1815</year>
</root>
Paste any of these into the JSON to XML converter to see the transformation, or click To JSON in the reverse direction to round-trip.
Attributes and Text Content
The standard JSON-XML convention treats keys prefixed with @ as attributes and a #text key as the element's text content. The same convention is used by xml2js, fast-xml-parser, and most JSON-XML libraries, so the conversion round-trips:
{
"user": {
"@id": "42",
"@active": "true",
"name": "Ada",
"bio": { "#text": "Mathematician", "@lang": "en" }
}
}
<?xml version="1.0" encoding="UTF-8"?>
<user id="42" active="true">
<name>Ada</name>
<bio lang="en">Mathematician</bio>
</user>
Without the @/#text convention, attributes and element text get the same JSON representation — the conversion loses the distinction and is no longer reversible.
Arrays Become Repeated Elements
A JSON array does not become a single element. Each item becomes a separate element with the same tag name — XML represents lists as repetition:
{
"users": {
"user": [
{ "name": "Ada" },
{ "name": "Alan" },
{ "name": "Grace" }
]
}
}
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user><name>Ada</name></user>
<user><name>Alan</name></user>
<user><name>Grace</name></user>
</users>
A single-item array and a single object can't be distinguished in XML on read — most parsers default to "object if one, array if many," which makes round-trips ambiguous. If you control both sides, configure the parser to always treat a known tag name as an array.
Escaping
Five characters need special treatment in XML; the first three in element text, plus the two quote characters in attribute values:
| Character | In element text | In attribute value |
|---|---|---|
& |
& |
& |
< |
< |
< |
> |
> (recommended) |
> (recommended) |
" |
(no escape needed) | " if attribute uses " |
' |
(no escape needed) | ' if attribute uses ' |
Skip these and the parser will either reject the document or silently misread it. Prepend the XML declaration (<?xml version="1.0" encoding="UTF-8"?>) so the output is a complete, parser-ready document.
Namespaces and Prefixes
XML namespaces appear as xmlns or xmlns:prefix attributes and qualify element and attribute names. In a JSON-friendly form, treat them as ordinary @xmlns / @xmlns:prefix attribute keys and keep prefixed names like soap:Envelope as the JSON key — most converters preserve the prefix verbatim:
{
"soap:Envelope": {
"@xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
"soap:Body": { "GetWeather": { "City": "London" } }
}
}
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><GetWeather><City>London</City></GetWeather></soap:Body>
</soap:Envelope>
Self-Closing vs Explicit Empty Elements
An empty JSON value maps to either a self-closing tag (<note/>) or a paired empty tag (<note></note>). Both are equivalent XML, but downstream parsers occasionally mishandle one form — prefer self-closing for compact output and explicit pairs when the consumer is known to be strict (some legacy SOAP / SAML implementations are picky).
Round-Trip Considerations
Several XML facts have no JSON equivalent and are dropped during conversion. Plan the round trip with these in mind:
| XML fact | What happens in JSON |
|---|---|
| Attribute order | Lost (JSON object keys are unordered in spec, though most parsers preserve insertion order in practice) |
Comments (<!-- … -->) |
Dropped |
Processing instructions (<?xml-stylesheet … ?>) |
Dropped |
CDATA sections |
Collapsed into the element's text (escaping behavior shifts) |
| Empty element vs missing element | Both can serialize as null or omitted; the distinction is lost |
| Mixed content (text interleaved with child elements) | Hard to represent — most converters concatenate or warn |
For data interchange these losses are usually fine; never use round-tripped XML where signature canonicalization (XML-DSig, SAML, SOAP-Sec) matters — re-serializing through JSON breaks the canonical byte sequence.
Common JSON-XML Converters
- JavaScript / TypeScript —
fast-xml-parser(the most maintained option in 2026) andxml2js(legacy but widely used) - Python —
xmltodict(uses the@/#textconvention by default) - Go —
encoding/xml(stdlib; struct-tag driven, less flexible for arbitrary JSON) - Browser —
DOMParserfor parsing,XMLSerializerfor serializing — built-in, no dependency
See also
This guide handles one format boundary. The hub lists every JSON ↔ neighbor-format conversion with its standard and edge cases.
Sources
- XML 1.0 specification — the canonical W3C reference for XML 1.0
- Namespaces in XML 1.0 — the namespace mechanism (the
xmlns:attributes) - RFC 8259 — the JSON Data Interchange Format (the conversion source)
fast-xml-parser— the actively-maintained JS reference parser
Last reviewed June 2026.
JSON repair guides
Topic hubs
- JSON Parse Errors: Read the Message, Jump to the Fix
- Fix Invalid JSON: From 'What's Wrong' to a Clean File
- JSON Formatter, Validator, Viewer: Pick the Right Tool
- Repair LLM JSON Output: Handling Almost-JSON from AI
- Privacy: JSON Tools That Don't Leave Your Browser
- JSON Interop: YAML, CSV, XML, JWT, Schema
Specific guides
- How to Decode Base64 Strings (and JWT Payloads)
- URL Encoding: Percent-Encode Query Parameters and Paths
- Convert YAML to JSON (and Avoid Indentation Errors)
- Convert JSON to CSV: Flatten an Array of Objects
- Escape JSON as a String Literal (and Decode Double-Encoded JSON)
- Fix Trailing Comma in JSON
- Fix Single Quotes in JSON
- Fix Unquoted Keys in JSON
- Repair LLM JSON Output
- Fix JSON Parse Error: Expected Property Name
- JSON vs JS Object Literal: The Key Differences
- Validate JSON Before API Requests
- JSON Formatter vs JSON Repair
- Fix JSON Unexpected Token Errors
- JSON to JavaScript Object Converter