JSON to XML

0 characters

Empty picks for you: a single top-level key becomes the root, anything else gets <root>.

Indent

Paste JSON on top, read the XML underneath. It updates while you type, so there is no Convert button to find. The conversion follows the convention Newtonsoft's Json.NET uses: @ for attributes and #text for text, and Json.NET's own ?xml, #cdata-section and #comment keys become the declaration, a CDATA section and a comment. Other libraries mark attributes their own way — xml2js puts them under a $ key and an element's text under _, and fast-xml-parser prefixes them with @_ unless you set attributeNamePrefix to @ — so rename those keys to @name and #text first, or they come out as elements. Every object becomes an element and every key becomes a child element. An array repeats its key, so a list of three tags becomes three tag elements side by side instead of a wrapper you then have to unwrap. Keys that start with @ become attributes, and a #text key becomes the element's own text. If your JSON is JSON-LD, where @context and @id are ordinary data, switch attributes off and they come out as elements instead. Two details matter more than they sound. First, numbers keep their exact digits. Most converters run your document through a standard JSON parser, which turns every number into a floating-point value, so an order ID like 12345678901234567890 quietly becomes 12345678901234567000. This one reads the digits as written and copies them into the XML unchanged. Second, when the JSON is broken, you get the line and column and the likely cause — a trailing comma, a single quote, a key without quotes, a comment — instead of a character offset. XML also refuses some things JSON allows. A key like first name or 2fa is not a legal element name, so it is renamed to first_name or _2fa and the page tells you which keys changed. A few control characters cannot appear in XML at all, even escaped, so they are replaced and counted. Everything runs in your browser; your JSON is never sent anywhere.

Built by Bob Article by Lace QA by Ben Shipped

How to use

  1. 1

    Paste your JSON into the top box, or press Sample to see a worked example with attributes, a repeated list and a null.

  2. 2

    Read the XML in the box below. It updates as you type. If the JSON has a mistake, a message names the line, the column and the usual fix instead.

  3. 3

    Leave Root element empty to let the tool choose: a document with a single top-level key uses that key as the root, and anything else is wrapped in <root>. Type a name to always wrap the document in that element.

  4. 4

    Pick an indent: 2 spaces, 4 spaces, or One line for compact XML with no whitespace between elements.

  5. 5

    Turn off XML declaration if you are pasting the result inside another XML document. Turn off @keys become attributes if your @ keys are data, as they are in JSON-LD.

  6. 6

    Check the notes under the result. They list any keys that were renamed to be legal XML names, any characters XML can't hold, and any empty arrays that produced no elements.

  7. 7

    Press Copy to put the whole XML document on your clipboard.

Frequently asked questions

Ratings & Reviews

Rate this tool

Sign in to leave a written review.
Loading reviews…

What does the JSON to XML converter do?

The JSON to XML converter takes a JSON document and writes the same data as well-formed XML. Objects become elements, keys become child elements, and lists become repeated elements. The output updates while you type. There is no Convert button, no upload step and no download gate. Your JSON never leaves the browser tab.

Press Sample and you get a small library record: a city, a name, an open flag, two books with IDs, some tags and a phone number set to null. The converter hands back this:

JSON (from the Sample)XML the tool writes
"@city": "London" on library<library city="London">
"open": true<open>true</open>
"books": [ {…}, {…} ]two <books> elements side by side
"@id": "b1" inside the first book<books id="b1">
"tags": ["sci-fi", "classic"]<tags>sci-fi</tags><tags>classic</tags>
"phone": null<phone/>

Under the result, a line reads 12 elements, 3 attributes. A note adds that one empty array wrote nothing. That's the second book's "tags": [], which has no items to repeat. The note is there so a missing element is never a mystery.

When you'll convert JSON to XML

Most new APIs speak JSON. A lot of the world still runs on XML. The gap between the two is where this tool lives.

Feeding an older system. Plenty of payment gateways, shipping carriers, government filing portals and bank interfaces take XML and nothing else. Your data sits in JSON because that's what your code produces. Paste it in and see what the XML looks like before you write the mapping code.

Writing a SOAP request or a config file by hand. Some build tools, feeds and enterprise configs are XML. Sketching the structure as JSON is faster. Converting it once gives you a starting file to edit.

Rebuilding XML from JSON. Something upstream turned XML into JSON, and now something downstream wants XML again. The converter follows the @-for-attributes and #text-for-text convention that Json.NET uses, and it reads Json.NET's other markers too. A top-level ?xml key is dropped, because the declaration comes from the XML declaration switch. #cdata-section becomes a CDATA section and #comment becomes a comment. Other libraries mark things their own way. xml2js puts attributes under a $ key and an element's text under _. fast-xml-parser prefixes attributes with @_ unless you set attributeNamePrefix to @. Rename those keys to @name and #text first, or they come out as child elements. Whichever library made the JSON, diff the result against the original XML before you rely on it. XML carries things no JSON shape records, like namespace declarations, entity references and the exact whitespace between elements.

Checking an ID survived. A standard JSON parser stores every number as a 64-bit float. A 20-digit order number comes out rounded, and nothing warns you. This tool shows you the digits in XML exactly as they were typed.

It works the same for a freelancer wiring up one client's invoicing feed, a student learning what an XML attribute is, and an engineer at a large company who needs the answer in thirty seconds and doesn't want to open a ticket for it.

How the conversion works

JSON and XML don't map one-to-one, so every converter has to make choices. These are the ones this one makes.

JSONBecomes in XML
An objectAn element. Each key becomes a child element, in the same order.
An array under a keyThat key's element, repeated once per item. No wrapper.
An array with no key (top level, or inside another array)One <item> element per entry.
A key starting with @, holding text, a number, true, false or nullAn attribute on the parent element.
A #text keyThe element's own text.
A #cdata-section or #comment keyA CDATA section, or an XML comment.
A top-level ?xml key (Json.NET's record of the declaration)Nothing. The declaration comes from the switch.
nullA self-closing element: <phone/>
"" (empty string)An open-close pair: <phone></phone>
A numberThe exact digits you typed. 1.500 stays 1.500.

Choosing the root element

XML needs exactly one root element. JSON doesn't. When the Root element box is empty, the tool decides. If the document is an object with one key, and that key isn't holding a list, the key becomes the root. So {"note": {…}} becomes <note>…</note>. Anything else gets wrapped in <root>. Type a name in the box and the whole document is always wrapped in that element instead.

Escaping

Ampersands and angle brackets are escaped everywhere, and double quotes are escaped inside attributes. So {"show": {"@title": "Tom & \"Jerry\"", "#text": "a < b && c > d"}} becomes <show title="Tom &amp; &quot;Jerry&quot;">a &lt; b &amp;&amp; c &gt; d</show>. Any XML parser reads that back as the original text.

Examples: what goes in, what comes out

Every row below is what the JSON to XML converter actually returns, with the XML declaration off and the One line indent picked, so each result fits in the table.

JSON you pasteXML you get
{"a": 1, "b": 2}<root><a>1</a><b>2</b></root>
{"tags": ["a", "b"]}<root><tags>a</tags><tags>b</tags></root>
{"p": {"#text": "Hello ", "b": "world"}}<p>Hello <b>world</b></p>
{"m": [[1, 2], [3]]}<root><m><item>1</item><item>2</item></m><m><item>3</item></m></root>
{"order": {"id": 12345678901234567890, "total": 1.500}}<order><id>12345678901234567890</id><total>1.500</total></order>
{"cart": {"items": [], "total": 0}}<cart><total>0</total></cart> plus a note about the empty array
"hello"<root>hello</root>

The mixed-content row is worth a second look. When an element has both its own text and children, the tool stops indenting inside it, even with 2 or 4 spaces picked. Indentation there would add spaces to the text itself, and Hello world would stop being Hello world.

The order row is the one a standard parser gets wrong. Run that JSON through JSON.parse and the ID comes back as 12345678901234567000, and the total as 1.5. The ID looks right and isn't. This tool reads the digits as text and copies them straight into the XML.

When the result isn't what you expected

If the output box stays empty and a red message appears, the JSON didn't parse. Start there. The message names the line and the column, then the usual fix. These are the ones you'll see most:

What's in your JSONWhat the tool tells you
A comma after the last itemtrailing comma before }. JSON doesn't allow a comma after the last item — delete it.
{'a': 1}keys need double quotes, not single quotes.
{name: "Ada"}the key `name` needs double quotes around it — JSON keys are always strings.
A // commentJSON has no comments. Delete the // or /* */ part and try again.
{"ok": True}True isn't JSON — it's written true, false or null, in lowercase.
{"zip": 02134}02134 isn't a valid JSON number — numbers can't start with 0. Drop the leading zero, or quote it if it's a code like a ZIP.
Two objects pasted one after anotherthere's more after the JSON value ended. If you have several objects, put them inside [ ] with commas between them.

For an unclosed bracket, the message points at where the bracket was opened, not where the file happened to end. the [ opened on line 2 is never closed with ]. That's the line you actually need to look at.

Keys that changed name

If the XML came out but some element names look odd, check the notes under the result. XML names can't start with a digit or hold spaces and most punctuation. So first name becomes first_name, 2fa becomes _2fa, and price ($) becomes price____. Keys in Japanese, Arabic or Cyrillic stay exactly as written, and xlink:href keeps its colon because that's how namespaces are spelled. The tool doesn't declare the prefix for you, though, and a namespace-aware parser rejects a prefix nobody declared. Add the declaration as an @ key on the element or an ancestor: {"a": {"@xmlns:xlink": "http://www.w3.org/1999/xlink", "@xlink:href": "#top"}} becomes <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#top"/>.

Characters XML can't hold

A few control characters, like the bell character U+0007, are legal inside a JSON string and illegal anywhere in XML 1.0, even escaped. The tool swaps each one for the replacement character � and counts them in a note. The output stays well-formed, and you know exactly how many were touched.

Tips for clean XML

  • Pick One line for machines, 2 or 4 spaces for people. One line writes the whole document with no whitespace between elements. That's the right choice when the XML goes into a request body or a single database column.
  • Turn off the XML declaration when you're nesting. If the result is going inside another XML document, a second <?xml …?> line in the middle makes the outer file invalid.
  • Name the root yourself when a system expects one. If the receiving side wants <Request>, type Request in the Root element box. A name that isn't legal XML is refused with a suggestion: my root gets Try my_root.
  • Want a list wrapper? Put it in the JSON. {"books": {"book": [ … ]}} writes one <books> holding a <book> per item. The tool never invents a wrapper you didn't ask for.

JSON-LD and schema.org data: keys like @context and @type are data there, not attribute markers. With attributes on, they land as context="…" and type="…" on the root. Switch @keys become attributes off and they come out as elements instead, renamed to <_context> and <_type> because an XML name can't start with @. The note lists both renames.

A converter, not a contract

Turning JSON into XML online usually goes one of two ways. You get a Convert button buried in ads, with a sign-up box between you and the download. Or the conversion is one connector inside an integration platform that bills per seat, runs on an annual contract, and now bundles an AI assistant into the renewal. Swapping curly brackets for angle brackets is not a subscription-sized problem.

So this is one page. Paste up to 5 MB of text and copy the result. There's no account, no trial clock, and no second tier where the real tool lives. This is the full tool.

If the JSON is a mess before you start, run it through the JSON formatter first. A missing comma is much easier to spot in indented JSON. Comparing two API responses before converting one? The JSON diff shows what changed. Heading somewhere other than XML? The JSON to YAML converter handles config files, and JSON to CSV flattens a list of records into spreadsheet rows. If your JSON is sitting inside a string full of escaped quotes, the JSON escape and unescape tool turns it back into something this converter can read.

Frequently asked questions

Can I convert XML back to JSON here?

Not on this page. It does one job, and that job is JSON to XML. The two directions aren't mirror images, either. XML carries namespaces, comments in odd places and whitespace that a JSON shape can't always record, so treat any trip from XML to JSON and back as something to diff, not something to trust.

Why is my root element called <root>?

Because your JSON had more than one top-level key, was a list, was a single key holding a list, or wasn't an object at all. XML allows exactly one root element, so the tool wraps the document in <root>. Type any legal name into the Root element box to change it. The name you type always wraps the whole document.

Does the XML keep the order of my keys?

Yes. Elements appear in the same order as the keys in your JSON. That matters because many XML schemas require elements in a fixed sequence. If a system complains about element order, reorder the keys in the JSON and the XML follows.

Will the output pass my XSD schema?

It's always well-formed XML 1.0. One catch: if your keys use a namespace prefix like dc: or og:, declare it with an @xmlns:dc key, or namespace-aware parsers will stop at the unbound prefix. Whether it's valid against a particular schema depends on your data: the right element names, the right order, the right attributes. The JSON to XML converter doesn't know your schema, so it writes exactly what your JSON describes and nothing more. Rename keys and add @ keys in the JSON until the shape matches.

Does it use CDATA sections?

Only when you ask for one. Ordinary text is escaped instead, so & becomes &amp; and < becomes &lt;. To an XML parser, escaped text and a CDATA section read back as the same string. Escaping also works inside attributes, where CDATA isn't allowed. To get a CDATA section, use a #cdata-section key the way Json.NET writes one: {"a": {"#cdata-section": "x < y"}} becomes <a><![CDATA[x < y]]></a>. A ]]> inside the text would end the section early, so the tool splits it across two sections and the text still reads back exactly.

Why not just ask an AI chatbot to convert it?

You can, and for ten lines it often works. But a language model writes the XML one token at a time, and nothing checks the result against your input. It can drop a digit from an ID, skip a repeated element or tidy up a key name, and the output still looks plausible. This converter follows fixed rules. The same JSON always gives the same XML, and every rename or dropped empty array shows up in a note.

Does it work on a phone?

Yes. It's the same tool on any screen, and nothing needs installing. Pasting a large API response on a phone is fiddly, but the conversion runs just as fast. Press Copy when you're done and the whole XML document goes to your clipboard.