StringToolsStringTools

JSON ↔ XML Converter

Convert JSON to XML and XML to JSON instantly. Two-way conversion, live preview, and 100% browser-based — your data never leaves your device.

Mitul MandankaFounder, Progragon Technolabs · 15+ years building software
Updated June 20268 min read

TL;DR

JSON and XML do not map onto each other one-to-one. JSON has six value types (object, array, string, number, boolean, null); XML has exactly one structure — nested elements that may carry attributes and text. The hard parts of any conversion are: arrays (XML has no array type, so they become repeated sibling elements), attributes vs elements (XML's id="5" has no JSON equivalent, so it gets a prefixed key), and round-trip loss (comments, namespaces, the XML declaration, and element order can disappear). The reference table below maps every JSON construct to its XML form so you know exactly what to expect before you paste.

JSON construct → XML representation: the full mapping

Because the two formats have different type systems, a converter has to make a decision for every JSON construct. This table shows the rule this tool applies (and the convention used by fast-xml-parser, which most JavaScript converters share). Read the "Caveat" column carefully — that is where round-trips break.

JSONXML outputCaveat
{"a": "b"} (object)<a>b</a>Each key becomes an element name. Keys must be valid XML names.
{"x": [1, 2]} (array)<x>1</x><x>2</x>No wrapper element — repeated siblings. A single-item array becomes a single element, which reverses back as a non-array.
"hello" (string)Text node: hello& < > are escaped to entities. Leading/trailing whitespace may be trimmed.
30 (number)Text node: 30Becomes a plain string in XML. On the way back, "30" is re-parsed to a number, so type survives by coincidence — not guarantee.
true (boolean)Text node: trueXML has no boolean type. The string true is re-parsed to a boolean on reverse — but the literal True would not be.
null<key/> (empty element)No native null in XML. An empty element reverses to an empty string "", not null — a silent type change.
{"@_id": "5"}id="5" (attribute)Keys prefixed @_ (this tool also accepts @, -, $) become attributes instead of child elements.
{"#text": "hi"}Text alongside attributes/childrenThe #text key holds an element's own text when it also has attributes or child elements.
Nested objectNested elementsMaps cleanly. Depth is unlimited; element order follows JSON key insertion order.

Attributes vs elements: the decision JSON can't make for you

In XML, the same information can be modeled two different ways, and the data itself is identical. These two are equivalent in meaning:

<!-- As an attribute -->
<book id="42">Dune</book>

<!-- As a child element -->
<book>
  <id>42</id>
  <title>Dune</title>
</book>

JSON has no concept of an attribute — it only has keys and values. So a converter needs a naming convention to distinguish the two when going both directions. This tool uses the @_ prefix (the fast-xml-parser default) when building XML, and on the way in it also accepts @, -, and $ as attribute markers. When parsing XML to JSON, attributes are stripped of their prefix entirely, so id="42" becomes a plain "id" key — which means you cannot tell, from the JSON alone, whether id was an attribute or a child element.

Practical rule: if you control the JSON and need it to round-trip to a specific XML shape, decide up front which fields are attributes and prefix only those with @_. Everything unprefixed becomes a child element. Mixing them after the fact is the single most common source of "the XML doesn't look right" bug reports.

Why arrays are the hardest part of JSON-to-XML

XML has no array type. A JSON array is represented as repeated sibling elements with the same tag name. That works going out, but it creates a real ambiguity coming back — because XML can't tell a one-item list from a single object.

JSON in:   { "skills": ["React", "Flutter"] }

XML out:   <skills>React</skills>
           <skills>Flutter</skills>

XML in:    <skills>React</skills>      (only one!)

JSON back: { "skills": "React" }        ← now a string, not an array

This is the "single-element array" problem and it is not a bug in any one tool — it is fundamental to the formats. A parser has no way to know whether a lone <skills> element is a scalar or a one-item list, so it defaults to a scalar. Two ways teams work around it:

  • A wrapper element. Model the array as <skills><item>React</item></skills> so the container is explicit. JSON-friendly, but verbose XML.
  • An XML Schema (XSD). If the parser knows from a schema that skills is maxOccurs="unbounded", it always produces an array. This tool does not consume an XSD, so it can't do this.

If your reverse conversion keeps collapsing single-item arrays, that is expected behavior — add a second element or post-process the result in code to force the field into an array.

What you lose in an XML → JSON → XML round-trip

Converting one way and back is not guaranteed to give you the original document. XML carries metadata that JSON has no place to store. Here is exactly what survives and what disappears with this converter's default settings.

XML featureSurvives?What happens
Elements & textYesMapped to keys and values cleanly.
AttributesValue yes, type noKept as keys, but you lose the marker that they were attributes, not elements.
Comments <!-- -->NoDropped. JSON has no comment syntax to hold them.
Namespaces xmlns:PartlyKept only as literal text in the key name (e.g. ns:tag); the binding to a URI is lost.
XML declarationNo<?xml version="1.0"?> is ignored on parse; this tool re-adds a default one when building.
Processing instructionsNo<?xml-stylesheet ...?> and similar PIs are discarded.
CDATA sectionsValue yesContent is preserved as text, but the <![CDATA[ ]]> wrapper is gone.
Element order across keysMostlyJSON object keys are ordered, so order usually survives — but two sibling elements with the same name get merged into one array, changing structure.

Bottom line: treat conversion as a one-way data transform, not a faithful document copy. If you need a byte-identical XML document back, keep the original — don't reconstruct it from JSON.

JSON ↔ XML conversion: questions people actually ask

Why did my XML attribute lose its @_ prefix when I converted to JSON?

By design. When parsing XML to JSON, this tool sets an empty attribute prefix, so id="5" becomes a plain "id": "5" key — clean, readable JSON. The trade-off is that you can no longer tell from the JSON whether id was an attribute or a child element. If you need a lossless round-trip, prefix attributes with @_ yourself before converting JSON back to XML.

Why does my single-item array come back as a string?

This is the single-element array problem, and it is inherent to XML — not a tool bug. A JSON array of one item becomes one XML element, and one XML element with no siblings looks identical to a scalar value. With no schema to consult, the parser defaults to a scalar. To force an array, ensure there are at least two sibling elements, or wrap the list in a container element like <items><item>...</item></items>.

How is JSON null represented in XML?

XML has no null type, so null becomes an empty element like <key/>. Watch the round-trip: converting that empty element back to JSON yields an empty string "", not null. If null-versus-empty matters in your data, handle it explicitly in code rather than relying on the conversion. Some standards instead use the xsi:nil="true" attribute, which this tool keeps as a literal attribute but does not interpret.

Will comments, the XML declaration, or namespaces survive conversion?

Comments and processing instructions are dropped entirely — JSON has nowhere to put them. The <?xml version="1.0"?> declaration is ignored on parse and a default one is re-added on build. Namespace prefixes survive only as literal text inside the key name (ns:tag stays ns:tag), but the binding from that prefix to its URI is lost. Don't use round-tripped output where namespace resolution matters.

Is converting XML to JSON the same as converting SOAP to REST?

No — they are related but different. Converting a SOAP response's XML body to JSON is a format change, which this tool does. Moving from SOAP to REST is an architecture change: different envelope structure, different error semantics, no WSDL, and different verbs. Use this converter to inspect or reshape the payload, but the protocol migration is a separate engineering task.

Why did a number or boolean become a string after conversion?

Everything in XML is text — there are no number or boolean types. When converting XML back to JSON, this tool re-parses values, so "30" becomes 30 and "true" becomes true. But this guessing is fragile: a US ZIP code like "01234" can lose its leading zero, and a version string like "1.0" may become the number 1. If exact typing matters, validate the output rather than trusting auto-detection.