XML ↔ JSON Converter

Convert between XML and JSON, with automatic attribute handling and array detection for repeated elements.

How to use the XML ↔ JSON Converter

  1. Paste XML into the left panel to generate matching JSON on the right, or paste JSON into the right panel to generate matching XML on the left.
  2. Or click Upload above the XML panel to load a .xml file from your device instead of pasting.
  3. Both panels stay live and editable — keep typing in either one and the other updates automatically a moment after you stop.
  4. Copy or download either panel's contents with its dedicated buttons.

See it in action

Given this XML:

<person>
  <name>Ada</name>
  <age>30</age>
  <active>true</active>
  <tags>
    <tag>algorithms</tag>
    <tag>math</tag>
  </tags>
  <address city="London" zip="EC1A 1BB"/>
</person>

The converter produces:

{
  "person": {
    "name": "Ada",
    "age": 30,
    "active": true,
    "tags": {
      "tag": [
        "algorithms",
        "math"
      ]
    },
    "address": {
      "@_city": "London",
      "@_zip": "EC1A 1BB"
    }
  }
}

Notice age became a real number, active became a real boolean, the repeated <tag> elements became a JSON array, and address's attributes became @_city/@_zip keys alongside its own object — all inferred directly from the XML's shape.

How This Tool Works

Whichever panel you edit drives the other: typing or pasting in the XML panel parses it and generates matching JSON on the right, and typing (or pasting) JSON generates matching XML on the left — there's no separate convert button or mode switch. Nothing you paste is ever sent to a server; parsing and building both run entirely in your browser.

XML attributes become JSON object keys prefixed with @_ (for example id="1" on a <user> tag becomes "@_id": 1). The prefix isn't cosmetic — it's what guarantees an attribute can never collide with a same-named child element on the same tag, since <user id="1"><id>2</id></user> needs both "@_id" and "id" to survive side by side in the output.

An element name that appears only once among its siblings converts to a plain JSON value or object; the same element name appearing two or more times anywhere among its siblings — not just consecutively — converts to a JSON array. This follows the shape of your XML automatically, but it means a JSON array with exactly one item converts back to a single plain tag, indistinguishable afterward from an element that was never meant to be a list — an inherent ambiguity of schema-less XML↔JSON conversion, not something this converter can resolve on your behalf.

Element and attribute text is type-inferred the same way this platform's other converters handle it: an unquoted true or false becomes a real JSON boolean, and a plain number becomes a real JSON number. Three cases are deliberately kept as strings instead: a leading-zero value like 007 (so a zip code or ID never silently loses its zeros), a hex-looking value like 0x2f (so a transaction hash or hex color never silently turns into a decimal number), and an integer too large to represent exactly as a JSON number (so a uint256-scale value never silently loses precision).

XML comments, the XML declaration, processing instructions, and DOCTYPE declarations are all dropped from the JSON output, since JSON has no equivalent for any of them — a warning banner tells you this only when your input actually contains one, so it never shows for plain, declaration-free XML.

CDATA sections are merged into their element's plain text — the underlying text is fully preserved, but the fact that it was originally wrapped in CDATA is not, since JSON has no CDATA concept to carry it forward. A warning banner appears whenever your input contains a CDATA section.

Text interleaved with child elements (mixed content, e.g. <a>Hello <b>World</b> Bye</a>) has no clean JSON equivalent — the separate text fragments are merged into one #text value, and their whitespace/ordering relative to the child elements isn't preserved. A warning banner appears whenever this happens.

Unlike this platform's YAML ↔ JSON Converter, which accepts a bare scalar as a valid JSON root, this converter requires exactly one root both ways: the XML side needs exactly one top-level element (XML itself has no valid syntax for more than one), and the JSON side needs a single object with exactly one top-level property to serve as that root element's tag name — a bare number, string, array, or a JSON object with zero or several top-level keys all show a clear error instead of guessing which one you meant.

Namespace-prefixed tags and attributes (like <soap:Envelope> or xmlns:soap="...") are kept exactly as written in the JSON key — the prefix is treated as a literal part of the name, not resolved against its namespace URI.

Converting JSON to XML checks that every object key is a legal XML element or attribute name (starts with a letter or underscore, and may contain a colon after that — e.g. soap:Envelope — but not as the first character; no spaces or other punctuation) and rejects a nested array of arrays (which has no key of its own to become a tag name) — both show a clear error naming the offending key instead of silently producing XML that won't parse anywhere else.

Frequently Asked Questions

Advertisement

Related tools

Advertisement