← All articles

JSON to XML: Root Elements, Arrays, and Attribute Mapping

Convert JSON to XML: choosing a root element, mapping @-prefixed keys to attributes, turning arrays into repeated elements, and escaping — in JS, Python, and online.

Converting JSON to XML is the reverse of a lossy mapping, which means you have to make choices JSON never forced you to make: what's the root element? Does this key become an attribute or a child element? How does a JSON array become repeated XML tags? This guide covers the conventions for JSON to XML — root elements, arrays, attributes, and escaping — in JavaScript, Python, and the browser.

Choosing a Root Element

XML requires exactly one root element; JSON has no such rule. So the first decision is what wraps everything. If your JSON is an object with a single top-level key, that key is the natural root:

{ "note": { "to": "Ada", "from": "Bob" } }

<note>
  <to>Ada</to>
  <from>Bob</from>
</note>

If the JSON has multiple top-level keys (or is an array), there's no single root, so converters wrap everything in a synthetic element such as <root>:

{ "to": "Ada", "from": "Bob" }

<root>
  <to>Ada</to>
  <from>Bob</from>
</root>

Attributes from @-Prefixed Keys

To round-trip with the XML-to-JSON convention, keys beginning with @ are emitted as attributes rather than child elements, and a #text key becomes the element's text content:

{
  "price": { "@currency": "USD", "#text": "9.99" }
}

<price currency="USD">9.99</price>

If you don't use this convention, every value becomes a child element — which is valid, just more verbose. The @/#text convention is what makes XML → JSON → XML lossless.

Arrays Become Repeated Elements

A JSON array doesn't become a single element with multiple values — it becomes the same element repeated, because that's how XML represents a list:

{ "tags": { "tag": ["a", "b", "c"] } }

<tags>
  <tag>a</tag>
  <tag>b</tag>
  <tag>c</tag>
</tags>

A subtle consequence: an array of objects at the top level can't be the root (it would produce multiple root elements), so it must be wrapped — commonly as <root> containing repeated <item> elements.

Values Without a Clean Mapping

  • Booleans and numbers — XML has no types, so true and 42 are written as the text true and 42.
  • null — usually an empty/self-closing element: <middleName/>.
  • Keys that aren't valid element names — names can't start with a digit or contain spaces. "1st place" isn't a legal tag and must be sanitised or it produces invalid XML.

Escaping and the Declaration

Text and attribute values must escape &, <, and > (plus " inside attributes). A converter should also prepend the XML declaration so the output is a complete document:

<?xml version="1.0" encoding="UTF-8"?>
<message>B &amp; C are &lt; D</message>

Targeting an XSD or Producing xmlns

If your consumer validates the XML against an XSD (XML Schema), the conversion has to do a few extra things beyond key→element mapping:

  • Element order matters. XML attributes on an element are unordered (per the spec), but child elements are ordered, and most XSDs enforce that order via xsd:sequence. Emit children in the order the schema expects, not in object-key iteration order, or validation will fail.
  • Namespace mapping. Re-create the xmlns declarations as @xmlns attributes on the root, and reflect any prefixed names back into the XML ("soap:Envelope"<soap:Envelope>). A converter that drops namespaces will produce XML that doesn't validate against any XSD that requires them.
  • Type-aware values. XML has no native types, so an XSD with xsd:int or xsd:date simply checks the text content matches. Format the JSON value as text the XSD's pattern expects (ISO date, integer-string, etc.).

How to Convert JSON to XML in Code

// JavaScript — a small recursive builder, or a library:
import { XMLBuilder } from 'fast-xml-parser';
const builder = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@' });
const xml = builder.build(jsonObject);

# Python — dicttoxml, or build with xml.etree.ElementTree
from dicttoxml import dicttoxml
xml_bytes = dicttoxml({"note": {"to": "Ada"}}, attr_type=False)

Convert JSON to XML Online

Paste your JSON into the JSON ⇄ XML converter and click To XML. It picks a sensible root, maps @ keys to attributes, repeats elements for arrays, and escapes special characters — all in your browser. If your JSON has syntax errors, it's repaired first; you can also clean it with JSON Fix.

Frequently Asked Questions

How do I convert JSON to XML?

Pick a root element (a single top-level key, or a synthetic <root>), then recursively turn keys into child elements, @-prefixed keys into attributes, and arrays into repeated elements — escaping &, <, and > in text.

How does a JSON array become XML?

Each array item becomes a separate element with the same tag name, because XML represents lists as repeated elements rather than a single multi-valued node.

How do I make a JSON value an XML attribute?

Prefix the key with @ (e.g. "@id") and put element text under #text. This matches the standard XML-to-JSON convention, so the conversion round-trips.

What happens if a JSON key isn't a valid XML element name?

XML tag names can't start with a digit or contain spaces, so keys like "1st place" must be sanitised (e.g. to _1st_place) or the output won't be well-formed XML.

Related Tools & Guides