Converters XML ⇄ JSON Converter

XML ⇄ JSON Converter

Convert XML documents to JSON, or JSON objects back into well-formed XML. Supports files up to 200MB.

Or convert a file directly — supports files up to 200MB

Drag & drop a file here, or click to browse

Processed in the background, so the page stays responsive even for huge files

How to use this tool

Pick a direction, paste or upload your file — the result updates instantly as you type. XML attributes are preserved as keys prefixed with @_, and text content uses a #text key when an element has both attributes and text. Malformed XML is caught immediately with a descriptive error.

Worked example: attributes and element text

This product record, pasted with XML → JSON selected:

<product id="p1">
  <name>Desk Lamp</name>
  <price currency="INR">1499</price>
  <sku>00731</sku>
</product>

comes out as:

{
  "product": {
    "name": "Desk Lamp",
    "price": {
      "#text": 1499,
      "@_currency": "INR"
    },
    "sku": "00731",
    "@_id": "p1"
  }
}
  • The id attribute becomes "@_id", listed after the child elements.
  • <price> has an attribute and text, so it becomes an object: the text under #text, the attribute under @_currency.
  • Text that looks like a number becomes a JSON number (1499), but a code with a leading zero stays a string, so "00731" keeps its zeros.

One item or a list? XML can't say

XML has no syntax for "a list with one item", so the same element can come back as two different JSON shapes. Here Asha has two tags and Ravi has one:

<customers>
  <customer>
    <name>Asha</name>
    <tag>gst</tag>
    <tag>annual</tag>
  </customer>
  <customer>
    <name>Ravi</name>
    <tag>gst</tag>
  </customer>
</customers>
{
  "customers": {
    "customer": [
      { "name": "Asha", "tag": ["gst", "annual"] },
      { "name": "Ravi", "tag": "gst" }
    ]
  }
}

Asha's tag is an array and Ravi's is a plain string (the output is shown here with each customer on one line). Code that loops over tag fails on Ravi, so accept both shapes, for example with [].concat(customer.tag ?? []). The same thing happens in reverse: with JSON → XML, [{"name":"Asha","tag":["gst","annual"]},{"name":"Ravi","tag":["gst"]}] becomes <root> with one <item> per object, and Ravi's one-item array is written as a single <tag>gst</tag>, which converts back as the string "gst", not ["gst"].

What doesn't survive

Comments are dropped, because JSON has nowhere to put them. <config><!-- owner: payments team --><retries>3</retries></config> converts to {"config":{"retries":3}}, and converting that back can't restore the note. Keep the original XML if comments or processing instructions carry information.

Frequently Asked Questions

Why do some JSON keys start with "@_"?

That prefix marks an XML attribute rather than a child element, since JSON has no built-in concept of attributes versus nested content — everything is just a key. An element like <book id="1"> becomes { "@_id": "1" } in the JSON output, keeping attributes distinguishable from child elements even after the structural difference between XML and JSON is flattened away.

What is the "#text" key for?

It appears when an XML element has both attributes and direct text content — for example <price currency="USD">29.99</price>, where the element has an attribute and a value at the same time. JSON objects need a key for every value, so the text portion gets the reserved #text key alongside the @_currency attribute key.

Can I round-trip XML → JSON → XML without losing anything?

For well-formed XML using standard elements, attributes, and text content, yes — the @_ and #text conventions preserve enough structure to rebuild equivalent XML. Things XML supports that JSON has no concept of at all, like comments or processing instructions, won't survive the round trip, since there's nowhere in JSON to put them.

Related Tools

Related Blog Posts