Skip to content

JSON to XML Converter

Paste JSON, get XML instantly. Converts objects, arrays, and @_ attributes in-browser — nothing uploaded. Free, private, no signup required.

No Tracking Runs in Browser Free
Options · 2 spaces · JSON → XML
Indent
0 chars
XML Output
0 lines
Reviewed for XML 1.0 well-formedness, @_/#text convention correctness, and root normalization accuracy — Go Tools Engineering Team · May 29, 2026

What is JSON-to-XML Conversion and How Does It Work?

JSON (JavaScript Object Notation) and XML (Extensible Markup Language) are both structured data formats, but they have fundamentally different models: JSON is a tree of objects, arrays, strings, numbers, booleans, and null values with no concept of attributes or document root constraints; XML is a tree of elements that may carry attributes and text content, and the document must have exactly one root element. Converting from JSON to XML requires a set of conventions to bridge this mismatch.

This tool uses the most widely adopted convention — the same one used by fast-xml-parser (Node.js), xmltodict (Python), and JAXB (Java) — applied in reverse:

**1. Root element normalization.** The single most important difference between JSON and XML is the root constraint. JSON has no root concept; XML requires exactly one. The converter handles four cases automatically. A single-key object uses that key as the XML root: { "config": {...} } → .... A multi-key object wraps in : { "a": 1, "b": 2 } → 12. A top-level array wraps as .... A primitive value wraps as value.

**2. @_ prefix → XML attributes.** JSON keys prefixed with @_ become XML attributes on the enclosing element. { "element": { "@_id": "42", "@_class": "primary" } } produces . This prefix is the canonical convention — no valid XML element name starts with @, so there is never a collision with child element names.

**3. #text → element text content.** When an element needs both attributes and text content, the text is stored under the #text key: { "price": { "@_currency": "USD", "#text": "29.99" } } → 29.99. Elements with only text content (no @_ keys) convert to plain text elements without this indirection.

**4. Arrays → repeated same-named sibling elements.** XML allows multiple child elements with the same name; JSON uses arrays for ordered lists. A JSON array under a key produces repeated child elements that reuse the key name: { "items": ["a", "b"] } produces ab (the two elements are siblings under the parent). When the entire JSON input is a top-level array, a wrapper is added and each element becomes an child — is a fixed fallback name used only in that case.

**5. Symmetric with XML-to-JSON.** The @_ and #text conventions used here are exactly the same conventions used by the companion XML to JSON Converter. This means a JSON → XML → JSON round-trip preserves attributes, text content, and element structure — as long as the input JSON follows the @_/#text conventions.

**When to convert JSON to XML?** The most common scenarios are: (1) sending data to a legacy SOAP or XML-based web service that requires an XML request body; (2) generating XML configuration files (Spring, Maven, Ant, Android resources) from JSON data; (3) producing sitemap.xml or RSS feed XML from JSON content data; (4) interoperating with enterprise systems (ERP, CRM, EDI) that consume XML; (5) generating SVG or other XML-based graphics formats programmatically from JSON data. For formatting and validating the resulting XML, use the XML Formatter.

// Convert JSON to XML in Node.js using fast-xml-parser
import { XMLBuilder } from 'fast-xml-parser';

const data = {
  catalog: {
    product: {
      '@_id': 'P01',
      '@_category': 'electronics',
      name: 'Wireless Headphones',
      price: {
        '@_currency': 'USD',
        '#text': '79.99'
      }
    }
  }
};

const builder = new XMLBuilder({
  attributeNamePrefix: '@_',   // @_ keys become XML attributes
  textNodeName: '#text',       // #text key becomes element text content
  ignoreAttributes: false,     // process @_ attribute keys
  format: true,                // pretty-print with indentation
  indentBy: '  ',              // 2-space indent
});

const xml = builder.build(data);
console.log(xml);
// <catalog>
//   <product id="P01" category="electronics">
//     <name>Wireless Headphones</name>
//     <price currency="USD">79.99</price>
//   </product>
// </catalog>

Key Features

Live Conversion

XML output updates instantly as you type or paste JSON — no Convert button needed. Large inputs (>200KB) automatically switch to manual mode to keep the browser responsive.

Automatic Root Normalization

XML requires exactly one root element. Single-key objects use their key as root; multi-key objects wrap in ; top-level arrays become ...; primitives become value — always valid XML output.

@_ Attribute and #text Convention

Keys prefixed with @_ become XML attributes; the #text key becomes element text content. This matches the fast-xml-parser and xmltodict convention, making the output symmetric with the companion XML to JSON Converter.

Array to Repeated Elements

JSON arrays under a key produce repeated child elements that reuse the key name — no singularization. { "items": [1, 2, 3] } yields three siblings. A top-level array input wraps as ... using as a fixed literal name.

100% Browser-Based Privacy

All conversion runs locally in your browser using JavaScript. Your JSON — including credentials, internal configs, and sensitive payloads — is never sent to any server, never logged, and never stored.

Symmetric Round-Trip with XML to JSON

The @_ and #text conventions are shared with the companion XML to JSON Converter. A JSON → XML → JSON round-trip faithfully preserves attributes, text content, and nested structure.

Examples

API Response Object

{"user":{"id":42,"name":"Alice Kim","email":"alice@example.com","role":"admin","address":{"city":"Seoul","country":"KR"}}}

A single-key JSON object where the top-level key becomes the XML root element. The nested address object produces a child

element with and children. Because the outer object has exactly one key ("user"), no wrapper is added — "user" itself is the root. Numbers like 42 become text content verbatim: 42.

Top-Level Array

[{"id":1,"name":"Widget A","price":9.99},{"id":2,"name":"Widget B","price":14.99},{"id":3,"name":"Widget C","price":4.49}]

When the entire input is a JSON array (not wrapped in an object), the converter produces .... Each array element becomes an child — "item" is a fixed literal wrapper name used exclusively for top-level arrays. This is the only case where appears; arrays under an object key reuse that key's name for every element instead.

Object with Attributes and Text Content

{"catalog":{"product":{"@_id":"P01","@_category":"electronics","name":"Wireless Headphones","price":{"@_currency":"USD","#text":"79.99"}}}}

Keys prefixed with @_ become XML attributes on the element: @_id becomes id="P01" and @_category becomes category="electronics" on the element. The #text key becomes the element's text content — so the price object produces 79.99. This round-trips cleanly with the XML to JSON converter, which uses the same @_ and #text conventions.

How to Use

  1. 1

    Paste Your JSON

    Enter or paste your JSON data into the input field above. You can also click 'Load example' to try a sample — an API response object, an array payload, or an object using @_ attributes and #text.

  2. 2

    See Live XML Output

    XML appears instantly in the output panel. Single-key objects use their key as the root; multi-key objects wrap in ; @_-prefixed keys become attributes; arrays become repeated child elements. Adjust indent (2 or 4 spaces) as needed.

  3. 3

    Copy or Download

    Click Copy to grab the XML to your clipboard, or Download to save it as a .xml file. To validate or reformat the result, paste it into the XML Formatter.

Common Conversion Pitfalls

Multi-Key Object Gets Unexpected Wrapper

If your top-level JSON has multiple keys, the output wraps them all in . This is correct XML (which requires a single root), but may not match your target schema. Reshape your JSON to a single-key object to control the root element name.

✗ Wrong
// Input: { "status": 200, "data": { "id": 1 } }
// Output: <root><status>200</status><data><id>1</id></data></root>
// Root is <root> — may not match your schema
✓ Correct
// Wrap in a named key to control the root element
// Input: { "response": { "status": 200, "data": { "id": 1 } } }
// Output: <response><status>200</status><data><id>1</id></data></response>

Top-Level Array Gets Wrapper

A top-level JSON array has no element name, so it is wrapped as .... If you want meaningful tag names, wrap the array in a named object first.

✗ Wrong
// Input: [{ "id": 1 }, { "id": 2 }]
// Output: <root><item><id>1</id></item><item><id>2</id></item></root>
// Tag names are generic
✓ Correct
// Wrap in a named key for meaningful tag names
// Input: { "products": [{ "id": 1 }, { "id": 2 }] }
// Output: <root><products><id>1</id></products><products><id>2</id></products></root>
// Each array element reuses the key name "products" as its tag

Attribute Keys Missing @_ Prefix

To produce an XML attribute, the JSON key must be prefixed with @_. Without the prefix, the key is treated as a child element, not an attribute.

✗ Wrong
// Input: { "tag": { "id": "42", "name": "Alice" } }
// Output: <tag><id>42</id><name>Alice</name></tag>  ← id is a child element
✓ Correct
// Use @_ prefix for attributes
// Input: { "tag": { "@_id": "42", "name": "Alice" } }
// Output: <tag id="42"><name>Alice</name></tag>  ← id is an attribute

Element with Both Attributes and Text — Missing #text

If you want an element to have both XML attributes and text content, you must use the #text key for the text. Without it, the text has nowhere to go and the element will be empty or produce an error.

✗ Wrong
// Input: { "price": { "@_currency": "USD", "value": "29.99" } }
// Output: <price currency="USD"><value>29.99</value></price>
// Text is a child element, not text content
✓ Correct
// Use #text for element text content
// Input: { "price": { "@_currency": "USD", "#text": "29.99" } }
// Output: <price currency="USD">29.99</price>  ← text content

JSON Keys with XML-Invalid Characters

XML element names cannot start with a digit or contain spaces, colons (except for namespace prefixes), or most special characters. If your JSON keys contain these characters, the output XML will be malformed. Rename offending keys before converting, or sanitize them in a post-processing step.

✗ Wrong
// JSON key starts with digit — invalid XML element name
// Input: { "1stItem": "value" }
// Output: <1stItem>value</1stItem>  ← invalid XML
✓ Correct
// Use a valid XML element name
// Input: { "firstItem": "value" }
// Output: <firstItem>value</firstItem>  ← valid XML

Special Characters in Values Not Escaped

XML text content must not contain raw <, >, &, or " characters — they must be escaped as <, >, &, and ". The converter automatically escapes these characters in element text content and attribute values. If downstream processing double-escapes them, verify that your XML parser is consuming raw XML bytes rather than re-escaping already-escaped content.

✗ Wrong
// JSON: { "query": "name = 'Alice' & role = 'admin'" }
// Converter outputs: <query>name = 'Alice' &amp; role = 'admin'</query>
// If double-processed: &amp;amp; — consumer is re-escaping
✓ Correct
// Converter output is correct — consume it as XML, not as a raw string
// <query>name = 'Alice' &amp; role = 'admin'</query>
// XML parser decodes to: name = 'Alice' & role = 'admin'

Common Use Cases

Calling SOAP and Legacy XML Web Services
Build the JSON payload in your application, convert it to XML, and POST it to the SOAP endpoint. This avoids hand-building XML strings and lets you work with the data in a native JSON structure up until the moment you need to serialize it for the legacy service.
Generating XML Configuration Files
Spring, Maven, Ant, Tomcat, and Android all use XML configuration formats. Generate or transform configuration data as JSON — easier to diff and version-control — then convert to XML for deployment.
Producing Sitemap and RSS Feed XML
Content management systems and static site generators often store page metadata as JSON. Convert that metadata to sitemap.xml or RSS feed XML to submit to search engines or syndicate content to feed readers.
Enterprise Data Integration (EDI / ERP / CRM)
ERP systems (SAP, Oracle), CRM platforms, and EDI networks commonly exchange data in XML. Convert JSON exports from modern REST APIs to XML to feed these systems without building a custom XML serializer.
Android Resource Files
Android string resources, layout constraints, and manifest entries are all XML. Generate or update resource files programmatically from JSON data sources and convert to the required XML format for the Android build system.
SVG and Vector Graphics Generation
SVG is XML. Build SVG structure as JSON data — paths, shapes, colors, transforms — then convert to XML to produce valid SVG files for web, print, or vector editing tools.

Technical Details

RFC 8259 Compliant JSON Parsing
JSON input is parsed using the browser's native JSON.parse(), which is fully RFC 8259 compliant. It provides accurate syntax error messages with best-effort position information (line and column) and handles all JSON data types: strings, numbers, booleans, null, arrays, and objects.
Custom Recursive JSON-to-XML Serializer
After parsing, a custom recursive serializer walks the JSON tree. Object keys that start with @_ are emitted as XML attributes on the parent element. The #text key is emitted as the element's text content. Plain object keys become child elements. Array values produce repeated same-named sibling elements. Special characters (<, >, &, ", ') in text content and attribute values are escaped to their XML entity references.
Root Normalization
Because XML requires exactly one root element, the serializer applies root normalization before building the document: single-key objects use the key as root; multi-key objects and top-level arrays receive a synthetic wrapper. This ensures output is always well-formed XML regardless of input shape.
100% Browser-Based — No Upload, No Server
All processing runs in your browser's JavaScript engine. No data is transmitted over the network at any point. Inputs larger than 200KB automatically switch from live mode to manual mode (requiring an explicit Convert click) to keep the browser responsive during heavy serialization.

Best Practices

Control the Root Element with a Single-Key Object
The cleanest way to produce meaningful XML is to ensure your top-level JSON is a single-key object whose key is the desired root element name. Wrapping multi-key data under one named key gives you a semantically meaningful root instead of the generic wrapper.
Use @_ and #text for Attribute-Heavy XML
If your target XML schema uses many attributes (common in configuration files, SVG, and SOAP envelopes), reshape your JSON to use @_-prefixed keys and #text before converting. The resulting XML will match the target schema exactly without post-processing.
Wrap Arrays in Named Objects for Meaningful Tag Names
A top-level array produces the generic ... pattern, where is a fixed literal name. Wrapping the array under a named key — { "products": [...] } — produces repeated elements (the key name is reused for every array element) under a wrapper. This gives you a domain-meaningful tag name and is almost always preferable for XML that will be parsed or validated by a schema.
Validate the Output with the XML Formatter
After converting, paste the XML output into the XML Formatter to validate well-formedness, check indentation, and identify any structural issues before sending the XML to a downstream service or committing it to version control.
Sanitize JSON Keys Before Converting
XML element names must start with a letter or underscore and may not contain spaces or most special characters. If your JSON keys come from an external source (a database column name, an API field name, or user input), audit them for XML name validity before converting to avoid malformed output.

Frequently Asked Questions

Is my JSON data sent to a server when I use this tool?
No. All conversion happens entirely inside your browser using JavaScript. Your JSON is never transmitted over the network, never stored on any server, and never logged or analyzed. This makes the tool safe to use with JSON payloads containing API credentials, database configuration, internal service data, or any other sensitive content. You can verify this by opening your browser's Network tab — you will see zero requests triggered by pasting or converting JSON.
How does the tool decide what the XML root element is?
XML requires exactly one root element; JSON has no such constraint. The converter applies these rules: (1) A single-key object uses that key as the root element name — { "user": { ... } } becomes .... (2) A multi-key object (two or more keys at the top level) is wrapped in a element so all keys become children of a single root. (3) A top-level array is wrapped as ..., with each array element becoming an child. (4) A primitive value (string, number, boolean, null) at the top level becomes value. These rules guarantee the output is always well-formed XML with exactly one root.
Why does a multi-key JSON object get wrapped in ?
XML is a document format with a strict single-root requirement — a valid XML document must have exactly one top-level element. JSON objects can have any number of top-level keys, so when your JSON has multiple top-level keys (such as { "status": 200, "data": {...}, "meta": {...} }), there is no single key to use as the root. Wrapping in is the safest and most predictable convention. If you want a different root element name, reshape your JSON to a single-key object before converting — e.g. { "response": { "status": 200, "data": {...} } }.
How does a top-level JSON array convert to XML?
A top-level array is wrapped as ....... Each array element becomes an child — "item" is a fixed literal name used only for top-level arrays. This is distinct from arrays nested under an object key: if you write { "products": [...] }, each array element becomes a child (reusing the key name), not . If you want custom tag names for a top-level array, wrap it in a named object first: { "products": [...] } gives you repeated elements.
How do I convert JSON keys to XML attributes?
Prefix the key with @_ and the converter will emit it as an XML attribute instead of a child element. For example, { "tag": { "@_id": "42", "@_lang": "en", "#text": "Hello" } } produces Hello. The @_-prefix convention is the same one used by fast-xml-parser (Node.js) and xmltodict (Python), making the output round-trip consistently with those libraries. This is also the convention used by the companion XML to JSON Converter.
What is the #text key used for?
When an element needs both XML attributes and text content, you cannot simply map the text to a child element — it must be the element's own text node. The #text key in your JSON becomes that text content. Example: { "price": { "@_currency": "USD", "#text": "29.99" } } produces 29.99. If an object has only a #text key and no @_ keys, it still produces a plain text element: { "note": { "#text": "hello" } } becomes hello.
Does indentation affect the XML structure?
No. Indentation is purely cosmetic — it changes how the XML is formatted for human readability but does not affect the element structure, attribute values, or text content. Choose 2 spaces for compact output or 4 spaces for more readable output. Both produce semantically identical XML. Most XML parsers treat whitespace-only text nodes between elements as ignorable whitespace, so indented and minified XML are equivalent for parsing purposes.
How does a JSON array nested inside an object convert to XML?
A JSON array value under a key produces repeated same-named child elements, reusing the key name for every element. For example, { "items": [1, 2, 3] } produces three siblings — not . Similarly, { "products": [{"name":"A"},{"name":"B"}] } produces two elements, each containing a child. The key name is used as-is for every array element; no singularization occurs. The only place the literal name appears is when the entire JSON input is a top-level array (see above), where is a fixed fallback wrapper name.
How do I convert XML back to JSON?
Use the companion XML to JSON Converter. It applies the same @_ and #text conventions in reverse: XML attributes become @_-prefixed JSON keys, element text content paired with attributes becomes a #text key, and repeated same-named sibling elements become a JSON array. The two tools are symmetric for round-trip use cases.
Can I validate or format the XML output?
Yes — paste the XML output into the XML Formatter to validate well-formedness, adjust indentation, or minify. The XML Formatter is the right tool for inspecting and polishing the XML once this converter has produced it.
Is there a file size limit for JSON input?
There is no hard limit, but inputs larger than 200KB automatically switch from live conversion to manual mode. In manual mode a Convert button appears and conversion runs only when you click it — this keeps the browser responsive during heavy serialization. For very large JSON files (multi-megabyte), consider command-line tools for better performance: node -e "const {XMLBuilder}=require('fast-xml-parser');console.log(new XMLBuilder({attributeNamePrefix:'@_'}).build(JSON.parse(require('fs').readFileSync('in.json','utf8'))))" or an equivalent Python script with xmltodict.
What JSON types are supported?
All six JSON types are supported. Objects become XML elements with child elements. Arrays become repeated same-named sibling elements. Strings, numbers, booleans, and null become element text content. Booleans and null are serialized as their literal string representations: true, false, and empty content for null. No type coercion is applied — numbers are written to XML text content exactly as they appear in the JSON, preserving decimals and precision.

Related Tools

View all tools →