Skip to main content

JSON to XML

Run Convert to see the result here.

Convert JSON to plain, readable XML, with your numbers and text copied exactly as written.

What it does

JSON to XML turns JSON into plain, readable XML: a declaration line, one root element, and one element for each value, named after its key. A list becomes the same element repeated once for each entry. Numbers and text are copied exactly as written.

XML has no numbers, true or false, null or lists, so the result is meant to be read and used as XML, not turned back into the same JSON. The tool either writes the XML or refuses and tells you why. It never changes your text or numbers; the only thing it adjusts is a key that XML cannot use as a name, by a fixed rule described below.

What it supports

  • Any JSON value can be the top level. The result starts with the line <?xml version="1.0" encoding="UTF-8"?> and has a single root element, root, that holds the whole document.
  • Each member of an object becomes an element named after its key. A member whose value is a list becomes that element repeated once for each entry, in order. A list at the top level, or inside another list, is written with item elements.
  • Strings, numbers and booleans are written as the text of the element. Numbers are copied exactly as written: 9007199254740993, 2.370 and 1e400 come out unchanged.
  • null and the empty object are written as a self-closing element such as <note/>. The empty string is written as an element with nothing between its tags, such as <note></note>. An empty list that is the value of a key leaves no element at all.
  • A key that is not a valid XML name is adjusted: each character that an XML name cannot hold becomes an underscore, an empty key becomes _, and a name that starts with a digit, a hyphen or a dot, or with the letters xml in any case, gets an underscore in front. So “1abc” becomes _1abc, “with space” becomes with_space and “x:y” becomes x_y. Accented letters, other alphabets and emoji are kept.
  • When two keys end up with the same name, for example “a b” and “a_b”, every element is kept, in order.
  • The characters & < > in text are escaped, and a carriage return is written as &#13;, so a literal <b> in a string never becomes an element and an XML reader gives each string back exactly. Quotes are left as they are.

Good to know

  • The XML cannot be turned back into the same JSON. XML has no types, so the number 1 and the string “1” are written alike, a list with one entry looks like a plain value, an empty list leaves no element, and null and the empty object are both self-closing elements. If you need to keep those differences, keep the JSON.
  • A name repeated inside one object is refused. XML readers disagree about which value wins, so the tool does not keep one and drop the other. Make the names unique and convert again.
  • A string with an unpaired surrogate escape, such as \ud800, is refused because it cannot be written faithfully in XML.
  • XML 1.0 forbids most control characters (such as \u0000, the backspace \b and the form feed \f), except tab, line feed and carriage return, and also the characters U+FFFE and U+FFFF. A string that contains one is refused. The tool never swaps or removes characters in your text. A forbidden character in a key does not cause a refusal, because the key is adjusted like any other invalid name.
  • Every refusal names its specific reason. For forbidden characters it does not give a line and column, so look in your JSON for control-character escapes such as \u0000.
  • The XML is larger than the JSON it comes from (tags, indentation, escapes). If the complete result would pass the size limit, it is refused with an incomplete preview (see below).

How to use it

  1. Paste or type your JSON in the input box. Nothing runs while you type.
  2. Choose the indentation (“2 spaces” or “4 spaces”) and press “Convert”.
  3. Read the XML next to your input. If the conversion is refused, the message says why.
  4. Press “Copy” to put the XML on your clipboard, or “Download” to save it as converted.xml.

Examples

Plain XML from JSON

Paste this JSON and press “Convert”. The result starts with a declaration and has one root element. The key “first name” is not a valid XML name, so it becomes first_name. The list is written as the element tags repeated once for each entry, the number 2.50 keeps its trailing zero, and null becomes a self-closing element.

{ "first name": "Ada", "tags": ["json", "xml"], "score": 2.50, "note": null }
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <first_name>Ada</first_name>
  <tags>json</tags>
  <tags>xml</tags>
  <score>2.50</score>
  <note/>
</root>

A character XML cannot hold

The text contains \u0007, the escape for a bell character. XML 1.0 does not allow it, so the tool refuses instead of changing the text.

{"note": "ring\u0007"}

A string contains a character that XML 1.0 does not allow, such as a control character. Changing the text would change your data, so the conversion was refused.

Repeated names

The name “id” appears twice in the same object, so the tool refuses instead of choosing one of the two values.

{"id": 1, "id": 2}

An object repeats a member name. Programs disagree about which value wins, so the conversion was refused instead of keeping one value and dropping the other. Make the names unique and try again.

What XML cannot tell apart

Paste this JSON and press “Convert”. In the result, n and s look alike, one looks like a plain value, empty is missing, and obj and nil are both self-closing elements.

{ "n": 1, "s": "1", "one": [1], "empty": [], "obj": {}, "nil": null }
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <n>1</n>
  <s>1</s>
  <one>1</one>
  <obj/>
  <nil/>
</root>

Limits and privacy

Size limits

  • Input: up to 2,000,000 bytes of UTF-8 text (about 2 MB). Accented letters and emoji take more than one byte each. Larger input is rejected.
  • Result: also up to 2,000,000 bytes. If the complete result would be larger, the tool shows only an incomplete preview of the first 100,000 bytes, and that preview cannot be copied or downloaded.
  • Nesting: up to 256 levels of objects and lists inside each other. Deeper JSON is refused because it is beyond what the tool processes.
  • Time: a run that takes longer than its time limit is stopped. Try a smaller input.

Your privacy

The text you type or paste, or open from a local file, is processed locally in your browser, in a dedicated Web Worker. It is never uploaded or sent to the server (a file you open is read in your browser only), and it is not written to storage, cookies or the address bar.

“Copy” puts the result on your clipboard and “Download” saves it as a file, but only when you press the button. The file is created in your browser, so nothing is uploaded.

For the full details, see the Privacy Policy

Related tools and pages

Your text stays in the page when you switch tools in the same tab, so you can try the same text in another tool. Reloading or closing the tab ends it.

All tools