Skip to content

📄 XML ⇔ JSON Converter

Convert XML ⇔ JSON in both directions. Supports attribute prefix, text node key, CDATA, and array auto-detection. Handles complex XML like RSS or SOAP.

100% Free No signup Browser-only 5 languages Dark mode

🔒 About Privacy

🔗 Related Tools

📖 Where people get stuck

Converts between XML and JSON, with a configurable attribute prefix, text-node key, CDATA handling and automatic array detection, so involved documents such as RSS or SOAP are within reach. Everything runs in the browser. Be aware, though, that the two have different data models, which makes the conversion inherently lossya round trip from XML to JSON and back does not reproduce the original file. Treat it as a one-way import.

Case What happens What to do
A round trip produced a different XML document JSON has no concept of attributes, no mechanism for preserving element order and no comments. So a round trip loses a great deal: the order attributes were written in, namespace prefixes (ns1: becoming ns2: is equivalent as XML), the distinction between <a/> and <a></a>, comments, the DOCTYPE, processing instructions and inter-element whitespace. Digital signatures are the serious case: XMLDSig signs the byte sequence itself, so a round trip breaks verification outright. For SOAP or electronic invoicing that is fatal. Design so that no round trip is needed. If you take XML in and use it inside your application, convert to JSON and either keep the original file for when you need to hand XML back, or regenerate it from a template. Where signing or verification is involved, the right answer is a library that works on the XML directly — treat the JSON conversion strictly as an aid to reading the content. If you want to know how lossy it is for your data, the fastest test is to round trip a document and diff it against the original: learning the limits with one deliberate experiment beats discovering them from an incident.
A repeated tag stops being an array when there is only one Automatic array detection judges by how many times the tag actually appears. Three <item> elements become an array; a single one becomes an object. That means the shape of the JSON depends on the data rather than on the schema, and consuming code dies on items.map(...). This is the single most commonly hit bug in XML to JSON conversion, and it is worse because test fixtures usually contain several entries, so it first breaks in production on the day there happens to be one. Importing RSS feeds or search results is where it classically appears. If you know the schema, always treat that element as an array. Most libraries offer an alwaysArray or arrayNotation option that lets you list the tag names that must always be arrays. Where the library gives you no such control, normalise on the consuming side with something like const list = [].concat(data.items?.item ?? [])making a habit of that one line very nearly eliminates this class of failure. Always include zero, one and many in your test fixtures: the first two are what break, and the first two are exactly what sample files omit.
Namespaced keys are awkward to use from JavaScript A <dc:creator> element becomes the key "dc:creator". The colon rules out dot notationobj.dc:creator is a syntax error. RSS and Atom always use namespaces, so anything that touches feeds hits this: content:encoded, media:thumbnail, itunes:duration. What makes it worse is that the prefix is chosen freely by each document — the same namespace URI may be dc: in one feed and dcterms: in another, so code that hard-codes a prefix stops working on the next feed. Access them with bracket notation, obj["dc:creator"]; TypeScript type definitions accept the same quoted key names. To cope with varying prefixes, normalising at import time is the only practical approach: either strip the prefix down to creator, or resolve via the namespace URI and rename to a short name of your own. Watch out that simply stripping prefixes can collidedc:date and atom:date both become date. Collecting five real feeds and trying them turns up prefixes you did not anticipate almost immediately, which is a faster check than reading the specifications.

Watch out for strings that look like numbers. Everything in XML is text, so <zip>007-0000</zip> and <tel>+81...</tel> are strings — but some conversion implementations coerce anything number-like into a number, and at that moment the leading zero disappears, 1e5 becomes 100000 and +81 becomes 81. Postcodes, phone numbers, product codes and version numbers must be configured to stay as strings. Second, when parsing XML from an external source on the server, mind XXE — external entity expansion. The browser DOMParser does not expand external entities, so this page is safe, but server-side parsers enable it by default in several implementations. In PHP that means not passing LIBXML_NOENT; in Java it means disabling external entities via setFeature. It is the classic read-any-local-file vulnerability, and it is still found in the wild routinely.

📖 How to Use

  1. 1
    Set direction and options
    Pick XML to JSON or JSON to XML, then choose attribute prefix, text key, and indent.
  2. 2
    Enter data
    Paste XML or JSON on the left. Use the Sample buttons to load RSS or JSON with attributes.
  3. 3
    Copy or download the result
    The converted output appears on the right in real time. Use Copy or Download to save it.

❓ Frequently Asked Questions

How are attributes and text nodes represented?
Attributes are stored under a prefixed key (e.g. @id) and text nodes under a chosen key (e.g. #text). The prefix and key name are configurable.
Are CDATA sections supported?
Yes. XML to JSON keeps CDATA content as plain text. JSON to XML automatically wraps values containing reserved characters in CDATA.
Are repeated tags converted into arrays?
When Array Auto is enabled, two or more siblings with the same tag are grouped into an array. When disabled, later occurrences overwrite earlier ones.
🐛 Found a bug or issue with this tool?

Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.

* Browser info (UA / screen / language / URL) is sent automatically to help reproduce the issue