How to Convert XML to JSON in JavaScript and Python
A default XML parser drops attributes, turns 007 into 7 and returns an object or an array depending on how many items there are. Here are the settings that fix all three.
To convert XML to JSON in code, a parser does most of the work, but its defaults decide what you lose. The XML to JSON Converter converts a document in the browser, and its page explains why there is no single correct mapping between the two formats.
This guide shows what a default parser does to a typical document, the options that keep the data intact in Node, and a short function for Python. Every output below comes from running the code.
What a default XML parser does to your data
<order id="ord_1">
<customer>Ana</customer>
<zip>007</zip>
<items>
<item><sku>A-1</sku><qty>2</qty></item>
</items>
</order>import { XMLParser } from "fast-xml-parser";
new XMLParser().parse(xml);
// {"order":{"customer":"Ana","zip":7,"items":{"item":{"sku":"A-1","qty":2}}}}- The
idattribute is gone. fast-xml-parser ignores attributes unless told otherwise. zipbecame the number7. Numeric-looking text is converted, and the leading zeros are lost.itemis an object. Add a second<item>and the same path becomes an array, so code that readsitems.item.skuworks for one order and breaks for the next.
Convert XML to JSON in Node.js without losing data
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "@",
parseTagValue: false,
isArray: (name, jpath) => jpath === "order.items.item",
});
parser.parse(xml);
// {"order":{"customer":"Ana","zip":"007","items":{"item":[{"sku":"A-1","qty":"2"}]},"@id":"ord_1"}}ignoreAttributes: falsekeeps attributes, andattributeNamePrefix: "@"marks them, so@idcannot clash with a child element namedid.parseTagValue: falsekeeps every value as a string. Convert numbers yourself, for the fields you know are numeric.isArrayforces the listed paths to always be arrays, whether the document has one item or many. List every repeating element of your format here.
Convert XML to JSON in Python
Python's standard library parses XML with ElementTree. A short function turns the tree into dictionaries, prefixing attributes with @:
import xml.etree.ElementTree as ET
def to_dict(element, list_tags=()):
children = list(element)
if not children and not element.attrib:
return element.text
result = {"@" + key: value for key, value in element.attrib.items()}
for child in children:
value = to_dict(child, list_tags)
if child.tag in list_tags:
result.setdefault(child.tag, []).append(value)
elif child.tag in result:
if not isinstance(result[child.tag], list):
result[child.tag] = [result[child.tag]]
result[child.tag].append(value)
else:
result[child.tag] = value
return result
to_dict(ET.fromstring(xml), list_tags={"item"})
# {'@id': 'ord_1', 'customer': 'Ana', 'zip': '007', 'items': {'item': [{'sku': 'A-1', 'qty': '2'}]}}ElementTree keeps text as strings, so 007 survives. The list_tags argument does the same job as isArray: without it, one <item> becomes a dictionary and two become a list.
Parsing XML from outside your system
XML has features that JSON does not, such as entity declarations, and some of them can be abused. Python's documentation warns that its XML modules are not secure against maliciously constructed data and recommends the defusedxml package for untrusted input. In Node, keep fast-xml-parser's entity options at their defaults unless you know you need more, and limit the size of the documents you accept.
Related tools
Convert JSON into well-formed XML with attribute and element control.
Parse any YAML config into strict, valid JSON your code can consume.
Parse CSV into a clean array of typed JSON objects, header-aware.
Pretty-print JSON with configurable indentation and instant validation.
Related guides
A library escapes the text for you, but it will happily write XML that is not valid. Here is tested JSON to XML code for Node and Python, and the three inputs that break it.
Two lines of code convert YAML to JSON, and the parser's defaults decide whether merge keys apply, dates stay strings and no means false. Here are the options that matter, tested.
A single quoted comma breaks the split approach. Here is correct CSV parsing in Python and JavaScript, the byte order mark that renames your first column, and safe type conversion.
Two formatters can disagree about the same JSON file. Here is how a team picks one, applies it in every editor and before every commit, and makes CI enforce it.