Skip to content
XML to JSON

XML to JSON

Convert XML to JSON online. Paste any well-formed XML and get a clean JSON object, with optional attribute preservation and array-detection.

Converts XML to JSON Preserves attributes (as @attributes) Auto-detects repeating elements as arrays Configurable indentation (2 / 4 / minify) Copy and download JSON output Import XML from URL or file Theme switcher Fullscreen editor mode

Input XML

Paste your XML here

JSON Output

Copy or download the converted JSON

Key Features

  • Converts XML to JSON
  • Preserves attributes (as @attributes)
  • Auto-detects repeating elements as arrays
  • Configurable indentation (2 / 4 / minify)
  • Copy and download JSON output
  • Import XML from URL or file
  • Theme switcher
  • Fullscreen editor mode

How to Use

  1. Paste your XML into the input editor.
  2. Toggle whether to keep attributes.
  3. Click Convert to produce JSON.
  4. Copy or download the JSON output.
  5. Need the reverse? Use the JSON to XML converter.

How the conversion works

Click Convert (or press Ctrl + Enter) and the XML is parsed by your browser's DOMParser. If the document is not well-formed, the parser error is shown and nothing is converted. Otherwise the tool walks the element tree from the root down, applying a small set of fixed rules:

  • The output is an object with one key, the root element's name.
  • An element with only text becomes a string. An empty element becomes "".
  • An element with child elements becomes an object keyed by child tag name, in the order each name first appears.
  • Two or more children with the same name become an array. A single child does not.
  • With Keep attributes checked, attributes go into an @attributes object, and any text on that element goes under #text.
  • Text is trimmed, and entities like & are decoded to the characters they stand for.

The result is printed with JSON.stringify using the indent you pick: 2 spaces, 4 spaces, or Minify for a single line.

Example: an order from a legacy API

<?xml version="1.0" encoding="UTF-8"?>
<order id="A-1042" currency="EUR">
  <customer>
    <name>Lena Fischer</name>
    <email>[email protected]</email>
  </customer>
  <items>
    <item sku="KB-01" qty="1">
      <title>Mechanical keyboard</title>
      <price>89.90</price>
    </item>
    <item sku="MS-07" qty="2">
      <title>Wireless mouse</title>
      <price>24.50</price>
    </item>
  </items>
  <note/>
  <paid>true</paid>
</order>

converts, with attributes kept and Indent: 2, to:

{
  "order": {
    "@attributes": { "id": "A-1042", "currency": "EUR" },
    "customer": {
      "name": "Lena Fischer",
      "email": "[email protected]"
    },
    "items": {
      "item": [
        {
          "@attributes": { "sku": "KB-01", "qty": "1" },
          "title": "Mechanical keyboard",
          "price": "89.90"
        },
        {
          "@attributes": { "sku": "MS-07", "qty": "2" },
          "title": "Wireless mouse",
          "price": "24.50"
        }
      ]
    },
    "note": "",
    "paid": "true"
  }
}

(The @attributes objects are shown on one line here to save space; the tool prints them expanded.) Notice that price, qty and paid are strings, and that the empty <note/> became an empty string. Your code can reach the first title with data.order.items.item[0].title.

Pitfalls when consuming the JSON

The single-item array problem

If the order above had only one <item>, items.item would be an object instead of an array, and item.map(...) would throw. This is the most common bug with any XML to JSON mapping, because XML itself cannot tell a list of one from a single value. Normalize with [].concat(items.item) before looping.

Element order between different names

Children are grouped by name, so <a>1</a><b>2</b><a>3</a> becomes {"a": ["1", "3"], "b": "2"}. The fact that b sat between the two a elements is gone. That is fine for records, but not for documents where sequence carries meaning, such as XHTML or DocBook.

Mixed content

For <p>Hello <b>big</b> world</p> the output is {"b": "big", "#text": "Hello world"}: all text pieces are joined into one #text value and the position of the bold word is lost. Rich text should be kept as XML or HTML.

Attributes turned off

Without attributes, <img src="a.png"/> becomes "". Keep attributes on for any format that stores data in them, such as SVG, Atom links, or Maven POM files.

What is not carried over

  • Comments and processing instructions are removed.
  • CDATA sections become ordinary strings, so <![CDATA[if (a < b)]]> turns into "if (a < b)".
  • Namespace prefixes stay in the key names ("media:thumbnail") and xmlns declarations appear as normal attributes. Namespace URIs are not resolved.
  • No type detection, no schema, and no option to rename @attributes or #text.

When to use a different tool

  • If conversion fails and the error is unclear, check the input in the XML Validator.
  • To reformat the JSON output or sort its keys, use the JSON Formatter.
  • To go the other way, use JSON to XML.
  • If the records are flat and you need a spreadsheet, convert here and then use JSON to CSV.

Frequently asked questions

How are XML attributes represented in JSON?

With Keep attributes checked, an element's attributes are collected into an object under the "@attributes" key, so they cannot collide with child element names. If that element also has text, the text goes under "#text". Uncheck the option to drop attributes entirely.

Why is one element an object and another an array?

Sibling elements with the same tag name are grouped into an array only when there are two or more of them. A single child stays a plain object or string. If your code expects an array, wrap single values yourself, for example with Array.isArray(x) ? x : [x].

Why are numbers and booleans output as strings?

XML has no data types without a schema: 44.95 and true in element text are just characters. The converter does not guess types, so every value is a JSON string. Convert them in your code, where you know which fields are numeric.

What happens to comments, CDATA, and namespaces?

Comments and processing instructions are dropped. CDATA content is treated as ordinary text, so it appears as a plain string. Namespace prefixes stay in the key names (for example "media:thumbnail"), and xmlns declarations appear as attributes.

Can I convert the JSON back to the same XML?

Not exactly. The order of differently named siblings, comments, and the position of text around child elements are lost in conversion, so a round trip produces equivalent data but not identical XML.

Does the tool send my XML anywhere?

No. Parsing uses the DOMParser built into your browser and the conversion runs in the page. Import URL fetches the file directly from your browser.

Latest from Our Blog

Tips, tutorials, and insights about web development