Skip to content
AgileLogics

JSON to XML

Serializes a JSON object into well-formed XML. "@name" keys become attributes and "#text" becomes text content, keys that aren't valid XML names are made valid, and the output is wrapped in <root> when the JSON has more than one top-level element.

Working on a whole file? Open it in the JSON editor →

How it works

Paste a JSON object with one top-level key (e.g. {"root": {...}}) and click Convert.

Turning a JSON object into XML

This converter takes a JSON object and writes it out as a well-formed XML document. Nested objects become nested elements, arrays become repeated elements with the same name, @ keys become attributes, and text values are escaped. The output is indented with two spaces and has no XML declaration.

JSON (RFC 8259) allows several top-level keys, but an XML document must have a single root element (XML 1.0, section 2.1). If your object has exactly one top-level key, that key becomes the root; otherwise the output is wrapped in <root>.

A complete example

Input:

{"order":{"id":1042,"customer":"Ana & Co","paid":true,"items":[{"sku":"A-1","qty":2},{"sku":"B-7","qty":1}],"note":null}}

Output:

<order>
  <id>1042</id>
  <customer>Ana &amp; Co</customer>
  <paid>true</paid>
  <items>
    <sku>A-1</sku>
    <qty>2</qty>
  </items>
  <items>
    <sku>B-7</sku>
    <qty>1</qty>
  </items>
  <note/>
</order>

Three things to see here. The ampersand in "Ana & Co" was escaped to &amp;. The items array produced two sibling <items> elements rather than one container, and null became the self-closing <note/>.

How each JSON value is written

JSON value XML produced
object {"a": 1} under key k <k> with a child <a>1</a>
array ["x", "y"] under key k <k>x</k> and <k>y</k> as siblings
nested array [[1, 2], [3]] under m <m> holding <item>1</item><item>2</item>, then <m> holding <item>3</item>
empty array [] no element at all
empty object {} or null under k self-closing <k/>
"@id": "b1" inside an object attribute id="b1" on that element
"#text": "12.50" inside an object the element's text content
string, number, true/false element text, as written

Text and attribute escaping covers &, <, > and ", so {"root":"<script>"} comes out as <root>&lt;script&gt;</root>. Control characters that XML 1.0 can't contain at all, even escaped, are replaced with the U+FFFD replacement character.

Number formatting follows JavaScript: 1.50 becomes 1.5, and integers larger than 2^53 lose precision because JSON.parse stores them as 64-bit floats.

Using it

  1. Paste the JSON object and click Convert.
  2. Look for <root> at the top of the output: it means your JSON didn't describe a single root element and the converter added one.
  3. Look for underscores in tag names you didn't write: they mark keys that were renamed (see below).
  4. Copy the XML and add a declaration line if your target needs one. The XML validator will confirm the result parses.

The two error messages you can get are "Enter valid JSON." (a syntax problem, which the JSON validator will locate for you) and a message asking for an object at the top level (you pasted an array or a single value).

How invalid key names are fixed

XML names can't contain spaces, can't start with a digit, and can't contain most punctuation, while JSON keys can be any string. Rather than write broken XML, the converter applies one rule: each disallowed character becomes _, and a name that can't start an XML element gets a leading _. So {"root":{"first name":"Ada","2nd":"x"}} gives:

<root>
  <first_name>Ada</first_name>
  <_2nd>x</_2nd>
</root>

A key with a namespace prefix, such as media:thumbnail, keeps its colon only when the prefix is declared with an @xmlns:media key on that element or one of its parents. An undeclared prefix would make the document invalid, so x:y without a declaration becomes x_y. If two attribute keys end up with the same name after renaming, the second gets an extra _.

Round trips with XML to JSON

JSON produced by the XML to JSON converter converts straight back: @ keys return as attributes, #text returns as text, and repeated elements return as siblings. Two things don't survive: the original order of interleaved sibling elements, and the position of text in mixed content. A #text array such as ["Hello", "again"] is written as one text run, Hello again, placed before the child elements. For re-indenting after manual edits, the XML formatter is handy.

When XML is the right target

Most new APIs speak JSON, but XML is still what you hand to SOAP services, RSS and Atom feeds, Android resource files, Maven and many enterprise integrations. For those, the output here is usually enough for a quick payload or test fixture. If the receiving system expects a specific schema, check the element names and attribute placement against it before sending.

Last updated

Frequently asked questions

What if my JSON has more than one top-level key?
An XML document must have exactly one root element. When your top-level object has one key, that key is the root. When it has several keys, no keys, or a single key holding an array, the output is wrapped in a <root> element so the result is still a valid document.
How are JSON arrays converted?
Each array item becomes its own element named after the array's key. {"tags": ["a", "b"]} produces <tags>a</tags> followed by <tags>b</tags>. There is no wrapping <tags> parent, so rename the key to the singular form (tag) if that reads better. An array directly inside another array becomes one element holding <item> children.
Can I create XML attributes?
Yes. A key starting with @ becomes an attribute of its element, and a #text key becomes the element's text: {"price": {"@currency": "EUR", "#text": "12.50"}} gives <price currency="EUR">12.50</price>. These are the same conventions our XML to JSON converter produces, so the two tools round-trip.
What happens to keys that aren't valid XML names?
They're made valid: every character XML doesn't allow in a name becomes an underscore, and a name that can't start an element (one starting with a digit, hyphen or dot) gets a leading underscore. "first name" becomes first_name and "2nd" becomes _2nd.
Does it add an XML declaration?
No. The output starts with the root element. Add <?xml version="1.0" encoding="UTF-8"?> on the first line yourself if the system you're feeding needs it.
Is the JSON sent to a server?
No. Parsing and serialising both happen in your browser, so nothing you paste leaves your device.