Skip to content

XML to JSON Converter

Convert XML to JSON in your browser. Attributes get @-prefixed; mixed content collapses.

    Runs entirely in your browser. Nothing is uploaded.

    This tool converts XML to JSON in your browser; nothing leaves your machine. For the reverse direction, see JSON to XML.

    XML and JSON have different data models

    XML is a markup language designed for documents; JSON is a data interchange format. They overlap but don’t map perfectly:

    XML featureJSON equivalent
    Element with textString
    Element with childrenObject with key-per-child
    Repeated elementsArray
    AttributesObject property (with prefix or in _attrs sub-object)
    Mixed content (text + elements)Awkward — needs convention
    NamespacesEncoded as part of element names
    CommentsDiscarded
    Processing instructionsDiscarded

    The conversion has to make decisions about each. There’s no canonical mapping.

    A typical conversion

    <user>
      <name>Alice</name>
      <age>30</age>
      <tags>
        <tag>vip</tag>
        <tag>active</tag>
      </tags>
    </user>
    

    →

    {
      "user": {
        "name": "Alice",
        "age": "30",
        "tags": {
          "tag": ["vip", "active"]
        }
      }
    }
    

    Notice:

    • The outer element wraps everything (XML requires a single root).
    • Numeric-looking values (30) become strings — XML has no native types.
    • The tag array is detected because there are multiple <tag> elements.
    • A single <tag> would have produced a string, not a 1-element array.

    The “single element vs array” problem

    The biggest XML-to-JSON conversion gotcha:

    With one tag:                      With two tags:
    <tags>                              <tags>
      <tag>vip</tag>                      <tag>vip</tag>
    </tags>                               <tag>active</tag>
                                        </tags>
    
    Becomes:                            Becomes:
    "tags": {                           "tags": {
      "tag": "vip"                        "tag": ["vip", "active"]
    }                                   }
    

    The shape of the JSON depends on the count. Consumers have to handle “string or array” types, which is awkward.

    Two solutions:

    • Always wrap in array. "tag": ["vip"] even when there’s one. Clean for consumers; bloats single-element cases.
    • Force a tag-list explicitly via schema. If the converter knows in advance which elements are repeatable, it can always emit an array for those.

    The tool above does neither: one element becomes a value and two or more become an array, so check the type before you index into it.

    Attributes

    <user id="42" type="admin">
      <name>Alice</name>
    </user>
    

    Attributes need a place in the JSON output. Conventions:

    // Convention A: Prefix attributes with @ or $
    {
      "user": {
        "@id": "42",
        "@type": "admin",
        "name": "Alice"
      }
    }
    
    // Convention B: Group attributes in a sub-object
    {
      "user": {
        "_attrs": { "id": "42", "type": "admin" },
        "name": "Alice"
      }
    }
    
    // Convention C: Mix attributes with elements (lossy if names collide)
    {
      "user": {
        "id": "42",
        "type": "admin",
        "name": "Alice"
      }
    }
    

    Convention A is the Badgerfish convention ($ prefix) and similar variants (@ prefix). Convention B is more verbose but never collides with element names. Convention C is simplest but loses the attribute-vs-element distinction.

    The tool above uses Convention B with the key @attributes, and puts an element’s own text under #text when it also has attributes: <user id="42">Alice</user> becomes {"@attributes": {"id": "42"}, "#text": "Alice"}. Attribute values stay strings. The root element’s own name isn’t kept — the output is its content.

    Mixed content

    XML allows text and elements to interleave:

    <p>Some <em>italic</em> text and <strong>bold</strong>.</p>
    

    JSON has no clean way to represent this. Conventions:

    // As an array of mixed values
    {
      "p": ["Some ", { "em": "italic" }, " text and ", { "strong": "bold" }, "."]
    }
    
    // As text with placeholders (lossy)
    {
      "p": "Some italic text and bold."
    }
    

    Mixed content is the hardest part of XML-to-JSON conversion. If your XML has it, the converter’s choice matters. The tool above is lossy here: child elements are grouped by name and the loose text is joined into one #text value, so the interleaving order is lost. Keep mixed-content documents (XHTML, DocBook) as XML.

    Namespaces

    <root xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:title>Example</dc:title>
      <dc:creator>Alice</dc:creator>
    </root>
    

    In JSON, namespace prefixes typically become part of the key:

    {
      "root": {
        "dc:title": "Example",
        "dc:creator": "Alice"
      }
    }
    

    The namespace declaration itself (xmlns:dc="...") becomes an attribute, which by Convention A is prefixed:

    {
      "root": {
        "@xmlns:dc": "http://purl.org/dc/elements/1.1/",
        "dc:title": "Example",
        "dc:creator": "Alice"
      }
    }
    

    Round-trip considerations

    XML → JSON → XML usually does not produce the original XML. Lost in conversion:

    • Attribute order.
    • Element ordering when objects deduplicate names (JSON object keys are unique; XML allows repeated children of the same name).
    • Comments and processing instructions.
    • Specific whitespace patterns.
    • The distinction between <elem/> and <elem></elem> (both render as the same JSON).

    For lossless round-tripping, use a converter explicitly designed for it (Badgerfish, JsonML, or similar canonical mappings).

    When XML-to-JSON is the right tool

    • Reading legacy XML APIs from JavaScript. SOAP services, RSS feeds, OData responses — easier to manipulate as JSON than as DOM.
    • Importing XML data into a JSON-based store. MongoDB, Elasticsearch, modern document stores expect JSON.
    • Converting XML configs to JSON. Rare but happens during modernization.

    When it isn’t

    • XML where order matters. JSON object key order isn’t guaranteed by the spec. If a downstream consumer depends on element order, you need an array-of-objects representation.
    • XML with rich schemas. XSD-validated XML loses its validation when converted; rebuilding equivalent constraints in JSON Schema is non-trivial.
    • XHTML and HTML. Convert to a JSON-of-DOM representation instead.

    Common pitfalls

    • Single-element arrays missing. <tags><tag>vip</tag></tags> becomes "tag": "vip" (a string), not "tag": ["vip"]. Consumers have to handle both. Use “always array” mode for predictability.
    • Attribute name collisions. An element with both an id attribute and a child element named id collides under Convention C. Use Convention A or B.
    • Lost whitespace. Insignificant whitespace between elements is dropped. If your “XML” is really mixed content where whitespace matters, the conversion is lossy.
    • Numeric coercion. Some converters auto-convert numeric-looking text to JSON numbers (<age>30</age> → "age": 30). Some don’t. The result affects how consumers parse — leading-zero strings ("007") are particularly affected.
    • Namespace flattening. Some converters strip namespaces; some preserve. Check the converter’s behavior.

    For the reverse direction, see JSON to XML. For other JSON conversions, JSON to YAML, JSON to CSV.