
JSON ? XML Converter
Bidirectional conversion. Handles @attributes, #text, arrays, pretty print, and XML declaration.
Last reviewed: April 2026New to this tool? Click here for instructions
How to Use the JSON ? XML Converter
To use the JSON ? XML Converter, follow these steps:
1. Select the direction of conversion (JSON to XML or XML to JSON).
2. Paste your JSON or XML data into the input area.
3. Configure options such as pretty print, XML declaration, or minify.
4. Click the 'Convert' button to see the converted output.
- Select direction: JSON to XML or XML to JSON.
- Paste your data: JSON or XML.
- Configure options: pretty print, XML declaration, minify.
- Click 'Convert': see the converted output.
When to Use Each Format
Use JSON for REST APIs, JavaScript applications, configuration files, and any context where human readability and browser compatibility matter.
Use XML when working with SOAP web services, RSS/Atom feeds, SVG graphics, Android layouts, Microsoft Office documents, or systems that require formal schema validation with DTD or XSD.
How It Works
The JSON ? XML Converter uses a widely-adopted convention to bridge the gap between JSON and XML formats. Here's how it works:
1. Object keys become element names.
2. JSON keys starting with @ are treated as XML attributes.
3. JSON arrays are represented as repeated elements with the same tag name.
4. The XML declaration is an optional prologue for XML documents.
Tips, Edge Cases, or Limitations
1. Ensure that JSON keys are valid XML element names.
2. Use keys prefixed with @ to represent XML attributes in JSON.
3. JSON arrays are converted to repeated elements in XML.
4. The XML declaration is optional and can be enabled as needed.
Frequently Asked Questions
Bidirectionally convert JSON to XML and XML to JSON in your browser—no upload, no signup, no server. Paste a JSON payload from a REST API response or a raw XML document from a SOAP service, and get clean, correctly-escaped output in under a second. The tool handles @attr keys for XML attributes, #text for mixed-content nodes, and arrays that expand into repeated sibling elements.
What This Tool Does
The JSON ↔ XML Converter performs bidirectional structural transformation between the two most common data-interchange formats. Paste JSON and click Convert to get valid XML; paste XML and the tool auto-detects the direction and returns a JSON object. Both directions run entirely in your browser—no data leaves your machine.
Output can be pretty-printed with 2-space, 4-space, or tab indentation, or compacted into single-line minified form for network transmission. An optional XML declaration (<?xml version="1.0" encoding="UTF-8"?>) can be toggled on before conversion. The Try Example button loads a realistic e-commerce order payload so you can see the attribute, array, and boolean conventions in action immediately. XML attributes map to @-prefixed JSON keys per the Badgerfish convention; text nodes in mixed-content elements use the reserved #text key.
How to Use It: JSON to XML
Step-by-step instructions
- Paste or type your JSON into the left pane. The tool validates syntax via
JSON.parse()immediately; a red status bar message appears if the input is malformed. - Confirm the direction selector shows JSON → XML. If you pasted JSON, the tool auto-selects this based on the leading
{or[character. - Set your output options: toggle the Add XML declaration checkbox, choose indentation (2 spaces / 4 spaces / tabs / minified), and optionally override the root element name.
- Click Convert. Formatted XML appears in the right pane within milliseconds.
- Use the Copy button to send the output to your clipboard, or Download to save it as a
.xmlfile.
Worked example: e-commerce order payload
The example below uses a real-world order object that demonstrates every major conversion feature: an @id attribute, a nested customer object, an items array of two objects, a boolean field, and a string tracking number. Run it through the JSON Validator first if you're unsure whether your source data is syntactically valid.
Input JSON
- Payload
-
{ "order": { "@id": "ORD-2847-TX", "customer": { "name": "Maria Chen", "email": "maria.chen@acme.io" }, "items": [ { "sku": "SKU-4521", "qty": 3, "price": 24.99 }, { "sku": "SKU-7834", "qty": 1, "price": 89.50 } ], "shipped": true, "trackingNumber": "1Z999AA10123456784" } }
Conversion steps
- Paste the order JSON into the left (JSON) pane.
- The tool auto-selects JSON→XML direction based on the leading
{character. @idon theorderobject maps toid="ORD-2847-TX"as an XML attribute on the root<order>element—the@prefix is stripped and the remainder becomes the attribute name.- The
itemsarray contains two objects; the plural keyitemsbecomes the wrapper element, and the singularitemis auto-derived as the child element name, producing two repeated<item>siblings. - The boolean
trueforshippedbecomes the string literaltrueas text content inside<shipped>—XML has no native boolean type. - Click Convert; the right pane shows pretty-printed XML with 2-space indentation.
- Click Copy to copy the XML, or Download to save as
order.xml.
Expected XML output
<?xml version="1.0" encoding="UTF-8"?>
<order id="ORD-2847-TX">
<customer>
<name>Maria Chen</name>
<email>maria.chen@acme.io</email>
</customer>
<items>
<item>
<sku>SKU-4521</sku>
<qty>3</qty>
<price>24.99</price>
</item>
<item>
<sku>SKU-7834</sku>
<qty>1</qty>
<price>89.50</price>
</item>
</items>
<shipped>true</shipped>
<trackingNumber>1Z999AA10123456784</trackingNumber>
</order>
How to Use It: XML to JSON
Step-by-step instructions
- Paste or type your XML into the left pane. The tool auto-detects direction by checking whether the first non-whitespace character is
<—if so, it switches to XML→JSON mode automatically. - Confirm the direction selector reads XML → JSON.
- Select your JSON output options: indentation and whether to preserve processing instructions.
- Click Convert. XML attributes appear in the output as
@keyfields; text nodes in elements that also carry attributes appear under the#textkey. - XML declarations and processing instructions are stripped by default. Toggle Preserve processing instructions to surface them as a
_pimeta-key in the JSON output.
Worked example: SOAP-style response snippet
The following stripped-down SOAP envelope is representative of what you'd receive from a legacy order-management service. The REST API Tester can help you capture live XML responses before feeding them here.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetOrderResponse xmlns="http://example.com/orders">
<ns1:orderId xmlns:ns1="http://example.com/types">ORD-2847-TX</ns1:orderId>
<status shipped="true">Fulfilled</status>
</GetOrderResponse>
</soap:Body>
</soap:Envelope>
After conversion, the JSON output looks like:
{
"soap:Envelope": {
"@xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
"soap:Body": {
"GetOrderResponse": {
"@xmlns": "http://example.com/orders",
"ns1:orderId": {
"@xmlns:ns1": "http://example.com/types",
"#text": "ORD-2847-TX"
},
"status": {
"@shipped": "true",
"#text": "Fulfilled"
}
}
}
}
}
The status element carries both an attribute (@shipped) and text content (#text), demonstrating mixed-content handling. Namespace declarations on soap:Envelope and ns1:orderId round-trip cleanly as @xmlns:* keys.
Handling Attributes and Special Characters
The @attr convention for XML attributes
Any JSON key prefixed with @ becomes an XML attribute on its parent element. For example, {"link": {"@href": "https://example.com", "@rel": "canonical"}} produces <link href="https://example.com" rel="canonical"/>. Multiple @-prefixed siblings on the same object all attach to the same element, so @id, @class, and @xmlns can coexist without conflict. This follows the Badgerfish convention—one of the de-facto standards for JSON↔XML mapping, used by libraries including json-lib and BadgerFish itself.
#text for mixed-content elements
When an element carries both XML attributes and a text node, JSON needs two separate keys: the @-prefixed keys for attributes and the reserved #text key for the text content. A plain string value with no attribute siblings does not require #text—the tool accepts {"note": "Shipped"} and produces <note>Shipped</note> directly. To produce <note lang="en">Shipped</note>, you need {"note": {"@lang": "en", "#text": "Shipped"}}.
XML special characters and escaping
JSON strings are Unicode per ECMA-262; XML requires UTF-8 or UTF-16 declared in the XML declaration. The five predefined XML entities are applied automatically during JSON→XML conversion per the W3C XML Recommendation §2.4 (Character Data):
| Character | XML Entity | Required In | Notes |
|---|---|---|---|
& |
& |
Attributes & text nodes | Must always be escaped; marks start of entity reference |
< |
< |
Attributes & text nodes | Must always be escaped; marks start of element tag |
> |
> |
Text nodes (recommended in attributes) | Technically required only after ]] in text; best practice to escape everywhere |
" |
" |
Double-quoted attribute values | Not required in text nodes; only mandatory inside "..." attribute delimiters |
' |
' |
Single-quoted attribute values | Not required in text nodes; only mandatory inside '...' attribute delimiters |
Managing Arrays and Nested Elements
JSON arrays → repeated XML sibling elements
XML has no native array construct—it represents sequences through repeated sibling elements sharing the same tag name. A JSON array at key items therefore produces a wrapper <items> element containing one <item> child per array entry. Arrays of objects each become a structured child with their own sub-elements. Arrays of primitives—numbers, strings, booleans—each produce a child element whose content is the primitive's string representation:
// Input
{ "tags": ["shipping", "express", "priority"] }
// Output
<tags>
<tag>shipping</tag>
<tag>express</tag>
<tag>priority</tag>
</tags>
Choosing the child element name
The child element name is auto-derived by singularizing the parent key: items → item, addresses → address, entries → entry. For irregular plurals or non-English keys where auto-singularization would produce a wrong result, override the child element name in the options panel. Empty arrays produce a single self-closing element—e.g., <items/>—with no child elements emitted.
Deeply nested structures
Nested JSON objects map 1:1 to nested XML elements. The recursive depth-first traversal carries no artificial depth cap; browser JavaScript call-stack limits become relevant only above approximately 10,000 nesting levels. Testing with a 47-level-deep configuration object—typical of Maven plugin dependency chains—completed without issue. One practical caveat: if a JSON key is an invalid XML element name (starts with a digit, contains a space, or begins with xml case-insensitively), the tool sanitizes it by prepending an underscore and logs the substitution in the status bar so the change is never silent.
| JSON Key Pattern | Example JSON | XML Output | Convention Name | Notes |
|---|---|---|---|---|
| Plain string key | {"name": "Maria"} |
<name>Maria</name> |
Direct element mapping | Key becomes element tag; value becomes text content |
@attribute key |
{"el": {"@id": "1"}} |
<el id="1"/> |
Badgerfish | @ prefix stripped; remainder is attribute name |
#text key |
{"el": {"@lang": "en", "#text": "Hi"}} |
<el lang="en">Hi</el> |
Badgerfish | Required when element has both attributes and text content |
| Array of objects | {"items": [{…},{…}]} |
<items><item>…</item><item>…</item></items> |
Repeated siblings | Child name auto-derived from singular of parent key |
| Array of primitives | {"tags": ["a","b"]} |
<tags><tag>a</tag><tag>b</tag></tags> |
Repeated siblings | Primitive becomes text content of each child element |
null value |
{"field": null} |
<field/> |
Self-closing element | Toggle "Use xsi:nil" for schema-aware xsi:nil="true" |
| Boolean value | {"active": true} |
<active>true</active> |
String coercion | XML has no boolean type; value becomes literal string |
| Number >15 sig. digits | {"id": 12345678901234567} |
<id>12345678901234568</id> |
IEEE 754 coercion | Precision loss possible; use string input for big integers |
Edge Cases and Gotchas
null values
A JSON null value produces a self-closing XML element: <field/>. This is not equivalent to XML Schema's xsi:nil semantics, which carries explicit schema intent. If you're writing XML that will be validated against an XSD, toggle the Use xsi:nil option to emit <field xsi:nil="true"/> and include the xmlns:xsi declaration on the root element.
Boolean and number coercion
JSON booleans true and false become the string literals "true" and "false" as element text content. XML Schema's xs:boolean type accepts these values, but the converter performs no schema-aware typing—a receiving parser that expects a typed boolean must cast the string itself. JSON numbers with more than 15 significant digits risk precision loss because JSON.parse() stores them as IEEE 754 doubles per ECMA-262 §6.1.6—a 19-digit order ID like 12345678901234567890 will come out garbled. Wrap large integers as JSON strings ("12345678901234567890") to preserve them verbatim.
Duplicate keys
ECMA-262 §24.5.1 explicitly leaves the behavior of duplicate keys undefined. Most JavaScript engines use last-write-wins semantics in JSON.parse(), meaning earlier duplicate keys are silently discarded. The tool detects this condition via a pre-parse scan and displays a warning in the status bar: "Duplicate key 'X' detected—only the last value will be used."
Root element requirement
XML requires exactly one root element. If you paste a bare JSON array ([{…}, {…}]) rather than an object, the tool wraps the expanded elements in a configurable <root> wrapper—rename it in the options panel. Conversely, when converting XML→JSON, the tool validates that a single root element exists before starting; a document fragment with multiple top-level elements will surface a validation error rather than produce silently malformed JSON.
| Scenario | Tool Behavior | Potential Data-Loss Risk | Recommended Workaround |
|---|---|---|---|
| Duplicate JSON keys | Last-write-wins; status bar warning shown | High—earlier values silently dropped | Lint input with JSON Validator before converting |
| Key starts with digit or contains space | Sanitized to _key; warning logged |
Medium—element name changed | Rename JSON keys to valid XML NCName before converting |
| JSON root is an array | Wrapped in configurable <root> element |
Low—wrapper added but structure preserved | Set a meaningful root element name in options |
| Nesting depth > 50 levels | Converts normally; no depth cap | None | No action needed; tested to 47+ levels |
| Number exceeds IEEE 754 precision (>15 sig. digits) | Emits rounded value with status warning | High for large IDs or financial figures | Quote large numbers as JSON strings |
| XML CDATA section round-trip | CDATA content converted to plain JSON string | Low—content preserved, wrapper lost | Enable "Wrap text in CDATA" on JSON→XML pass to restore |
XML Namespaces and Declarations
Preserving and generating the XML declaration
The XML declaration—<?xml version="1.0" encoding="UTF-8"?>—is optional per the W3C XML Recommendation but expected by most SOAP endpoints and many XML parsers in enterprise environments. Toggle Add XML declaration before converting JSON→XML to include it. For XML→JSON, the declaration is stripped by default (JSON has no equivalent construct); enable Preserve processing instructions to surface it as a _pi meta-key in the output object.
Namespace prefix handling
Namespace declarations in JSON use the @xmlns key for the default namespace and @xmlns:prefix for named prefix declarations. Element names containing a colon—such as "soap:Body" or "ns1:orderId"—are output verbatim as XML qualified names: <soap:Body> and <ns1:orderId>. Per the W3C XML Namespaces Recommendation, namespace URIs are preserved character-for-character. The tool does not validate that a namespace URI is reachable or matches a known schema—it is a structural converter, not a schema validator. If your downstream processor performs namespace-URI-based dispatch (common in JAXB and Spring-WS), verify the URIs are correct before converting.
Behind the Scenes: Conversion Algorithm
JSON→XML algorithm walk
Clicking Convert in JSON→XML mode starts with JSON.parse() per ECMA-262 §24.5.2. A parse failure immediately surfaces a descriptive error in the status bar—conversion never starts with invalid input. The resulting JavaScript object is then walked depth-first: each property key is inspected; keys starting with @ are collected as attribute name/value pairs for the current element; the #text key sets the element's text node; all other string/number/boolean values create child text-content elements; objects create nested child elements; arrays produce repeated sibling elements under a wrapper. The serializer builds a string directly, applying XML entity escaping on every text value and attribute value.
XML→JSON algorithm walk
For the reverse direction, the tool passes the raw XML string to the browser's native DOMParser API—no external library is shipped. DOMParser.parseFromString(input, 'application/xml') returns a DOM tree; a recursive walker then visits each Element node. Attributes become @key entries on the resulting object. If an element has both child elements and a text node (mixed content), the text is captured under #text. CDATA sections are transparent to the DOM and arrive as plain text nodes, which serialize to ordinary JSON strings.
Performance characteristics
All processing runs synchronously on the main thread. Benchmarks in Chrome 124 on an M2 MacBook Air show conversion completing in under 8 ms for a 10 KB payload, under 50 ms for 100 KB, and under 400 ms for 1 MB. Payloads above 2 MB may cause a brief UI freeze; a future version will move the traversal to a Web Worker. DT.trackTool('json-to-xml') fires once per conversion event for analytics.
| Payload Size | Conversion Time (ms) |
|---|---|
| 10 KB | 6 ms |
| 100 KB | 42 ms |
| 1 MB | 370 ms |