Nexinon

JSON ⇄ XML

Converts JSON to XML and XML to JSON, in both directions, with error diagnostics.

You can also drag and drop a file here.

XML indentation

Root element name

Item name (root-level array)

The "@" and "#text" convention

JSON has no concept of an XML attribute (`<item id="1">`) — only objects, arrays, and values. To represent both directions without losing that distinction, this tool uses a convention: a key prefixed with "@" becomes an attribute (`{"@id": "1"}` ↔ `id="1"`), and the key "#text" becomes the text of an element that also has an attribute or child (`{"@id": "1", "#text": "value"}` ↔ `<item id="1">value</item>`). A leaf element with no attribute skips "#text" — it becomes the value directly (`{"name": "Ada"}` ↔ `<name>Ada</name>`). This is the most common convention in the ecosystem (used by libraries like xml-js and fast-xml-parser), but it's worth knowing: **there's no universal standard for JSON ⇄ XML** — another tool may use a different convention.

Arrays and the way back to JSON

XML has no native array — a list becomes repeated elements with the same name (`<item>a</item><item>b</item>`). On the way back (XML → JSON), 2 or more sibling elements with the same name become an array; **exactly 1 element does not become an array** — it's indistinguishable from a plain value, because XML never records the intent "this is a list with just one item". A single-item array (`{"tags": ["a"]}`) converted to XML and back to JSON loses the "[ ]" (`{"tags": "a"}`). This tool warns on screen whenever it detects that case in the input — never silently.

Namespaces (xmlns, prefixes)

An XML with a namespace (`xmlns="..."`, elements like `ns:tag`) is handled literally: `xmlns`/`xmlns:*` become plain attributes, and the prefix (`ns:`) stays part of the key/element name, with no URI-based resolution. That correctly covers the most common real case — a document (SVG, RSS, config) using the same prefix consistently throughout — but it isn't full namespace support: this tool never recognizes two different prefixes pointing at the same URI as "the same namespace".

Root element and XML declaration

XML requires exactly one root element — but the top-level JSON value can be an object, an array, or even a bare value, none of which has a "name". That's why, when converting JSON → XML, you choose the root element's name (and, when the input is a root-level array, the name repeated for each item). The `<?xml version="1.0" encoding="UTF-8"?>` declaration is included by default, with an option to omit it.

Known limitations

All text content of an XML element/attribute becomes a string in JSON — numbers and booleans are never inferred automatically (XML has no type; inferring one would invent information the source XML never had). `null` in JSON and an empty element (`<a/>`) convert to the same thing in both directions — XML doesn't distinguish "absent" from "empty". This tool doesn't validate against a DTD/XSD (see the XML Formatter for well-formedness validation).

Frequently asked questions

No. All conversion happens in your browser — the JSON or XML you paste here never travels over the internet and is never logged anywhere.

Because XML has no array — a list is just repeated elements with the same name, and a single element is indistinguishable from a value that was never a list. See the "Arrays and the way back to JSON" section above — this tool always warns when it detects the case in the input.

"@name" represents an XML attribute (`id="1"`); "#text" represents the text of an element that also has an attribute or child element. It's this tool's own convention, not a universal standard — see the "The '@' and '#text' convention" section above.

No — prefixes (`ns:tag`) and `xmlns` are handled as literal text, with no URI-based resolution. It works correctly for the common case (a document with a consistent prefix, like SVG or RSS), but it doesn't recognize two different prefixes as the same namespace.

Because XML has no type — all content is text. This tool never infers whether a piece of text "looks like" a number or boolean, so it never invents information the source XML never had.

It only exists in JSON → XML, since JSON has no top-level name and XML requires exactly one root element. Two fields: the root element's name itself, and the name repeated for each item when the input is a root-level array.

File upload accepts up to 5 MB. Pasting directly into the text field has no technical limit, but very large inputs may slow the browser down.

Nexinon Principles

Privacy

Your data never leaves your browser.

No account needed

Use it now, no account or password.

Free

No usage limits, no paid plan.

Trustworthy content

Full explanation behind every tool, not just the result.
See the live proof — Trust Center

Other Data tools

View all