You have an XML file from an old system, an API that expects JSON, or a JSON response that needs to go back into an XML-based workflow. After reading this, you should be able to convert XML to JSON and JSON to XML without losing attributes, arrays, namespaces, or important text values.
The main challenge is not the conversion button or command. It is deciding how your XML structure should map to JSON, then checking the output so another app can actually read it.
Understand the XML-to-JSON mapping before you convert
XML and JSON do not describe data the same way. XML uses elements, attributes, text nodes, namespaces, and ordering. JSON uses objects, arrays, strings, numbers, booleans, and null values. A converter has to make choices, and those choices affect whether your output is usable.
Take this XML:
```xml
A common JSON conversion looks like this:
```json { "product": { "@id": "A-100", "@active": "true", "name": "Desk Lamp", "price": { "@currency": "USD", "#text": "39.99" }, "tags": { "tag": ["lighting", "office"] } } } ```
Notice the important details:
That last point causes many real-world bugs. If your receiving application expects an array, make sure the converter always outputs an array for repeatable fields, even when there is only one item.
For example, this XML:
```xml
may become:
```json { "tags": { "tag": "lighting" } } ```
But your code may expect:
```json { "tags": { "tag": ["lighting"] } } ```
Before converting a large file, convert a small sample that includes attributes, empty fields, repeated nodes, special characters, and nested elements. If that sample looks right, the full file is much more likely to behave.
Convert XML to JSON using a practical workflow
For one-off conversions, an online converter or editor is usually enough. For repeatable work, use a script so the same rules are applied every time.
Step 1: Clean and validate the XML first
Start by opening the XML in a code editor such as VS Code, Notepad++, Sublime Text, or any XML-aware editor. Check for the basics:
This is valid:
```xml
This is not:
```xml
The `&` character is a common problem. In XML text, use `&`. For `<`, use `<`. For `>`, use `>` when needed. Most JSON parsers are forgiving about regular text, but XML parsers are not.
If the file came from an export, also check the encoding line:
```xml ```
Use UTF-8 unless you have a specific reason not to. If names, accents, currency symbols, or non-English text look broken after conversion, encoding is the first thing to inspect.
Step 2: Decide how to handle attributes
Attributes are useful in XML, but JSON has no separate attribute concept. Most converters preserve them using a prefix.
A clear convention is:
```json "@id": "123" ```
or:
```json "_id": "123" ```
Use one convention and keep it consistent. If you are sending JSON to an API, check the API’s expected field names. It may not accept `@id`; it may expect `id`.
For internal use, keeping the prefix is safer because it preserves the difference between this:
```xml
and this:
```xml
Both contain an ID, but they are not structurally identical.
Step 3: Convert a representative sample
Do not start with a 200 MB XML file. Copy 20 to 50 records into a test file and include edge cases:
Example empty XML elements:
```xml
These might convert to:
```json "middleName": "", "phone": null ```
or:
```json "middleName": {}, "phone": {} ```
Different converters handle them differently. If your API expects an empty string, do not accept `{}` without adjusting the output.
Step 4: Format and inspect the JSON
After conversion, pretty-print the JSON with 2-space indentation. Avoid tabs if the file will be reviewed by multiple people because spacing looks different across editors.
Check these details:
If your next step is not XML but a spreadsheet or data feed, consider whether your data should be flattened first. For tabular data that starts in CSV, BestAIFinds has a simple CSV to JSON tool that is often cleaner than converting CSV to XML and then XML to JSON.
Convert XML to JSON with code
If you convert files regularly, scripting is safer than manual conversion because you can lock in the same rules.
JavaScript example with fast-xml-parser
Install:
```bash npm install fast-xml-parser ```
Use this script:
```js const fs = require("fs"); const { XMLParser } = require("fast-xml-parser");
const xml = fs.readFileSync("input.xml", "utf8");
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: "@", textNodeName: "#text", parseAttributeValue: false, parseTagValue: false, trimValues: true, isArray: (name, jpath) => { return ["products.product", "product.tags.tag", "orders.order"].includes(jpath); } });
const json = parser.parse(xml);
fs.writeFileSync("output.json", JSON.stringify(json, null, 2), "utf8"); ```
The important settings:
Keeping values as strings is often safer during conversion. You can transform types afterward when you know which fields should be numbers, booleans, or dates. Otherwise, a value such as `"00123"` may become `123`, losing the leading zeros.
The `isArray` option is especially useful. It lets you force known repeatable paths to arrays even when only one item appears.
Python example with xmltodict
Install:
```bash pip install xmltodict ```
Script:
```python import json import xmltodict
with open("input.xml", "r", encoding="utf-8") as f: xml_data = f.read()
data = xmltodict.parse( xml_data, attr_prefix="@", cdata_key="#text", force_list=("product", "tag", "order") )
with open("output.json", "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ```
Use `ensure_ascii=False` if you want characters like `é`, `ñ`, and `€` to remain readable instead of being escaped. The JSON is still valid either way, but readable output is easier to review.
`force_list` is the setting that prevents one-item lists from becoming plain objects or strings. Add every repeatable element name that your data model uses.
Convert JSON back to XML without surprises
Going from JSON to XML is not always a perfect reverse operation. If the JSON was created from XML using a known convention, you can usually rebuild it. If the JSON came from an API with no XML history, you need to design the XML structure.
Start with this JSON:
```json { "product": { "@id": "A-100", "@active": "true", "name": "Desk Lamp", "price": { "@currency": "USD", "#text": "39.99" }, "tags": { "tag": ["lighting", "office"] } } } ```
The XML should become:
```xml
JavaScript example with fast-xml-parser
```js const fs = require("fs"); const { XMLBuilder } = require("fast-xml-parser");
const json = JSON.parse(fs.readFileSync("input.json", "utf8"));
const builder = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: "@", textNodeName: "#text", format: true, indentBy: " ", suppressEmptyNode: false });
const xml = builder.build(json);
fs.writeFileSync("output.xml", xml, "utf8"); ```
Use `format: true` for readable XML. Use `suppressEmptyNode: false` if your receiving system distinguishes between:
```xml
and:
```xml
Some systems treat them the same, but older importers sometimes do not.
Python example with xmltodict
```python import json import xmltodict
with open("input.json", "r", encoding="utf-8") as f: data = json.load(f)
xml = xmltodict.unparse( data, pretty=True, indent=" ", full_document=True )
with open("output.xml", "w", encoding="utf-8") as f: f.write(xml) ```
This produces an XML declaration at the top because `full_document=True`:
```xml ```
If you are pasting the XML into another document or SOAP body, you may need `full_document=False` to avoid having an XML declaration in the middle of another XML file.
Common mistakes and how to fix them
Mistake 1: Losing attributes
If this XML:
```xml
becomes:
```json { "user": { "name": "Rina" } } ```
your converter ignored attributes. Look for a setting named `ignoreAttributes`, `preserveAttributes`, or `attributes`. Set it so attributes are included. In code, choose a prefix such as `@`.
Mistake 2: Arrays changing shape
A file with two invoices may produce:
```json "invoice": [ { "id": "1" }, { "id": "2" } ] ```
A file with one invoice may produce:
```json "invoice": { "id": "1" } ```
This breaks code that loops over invoices. Force lists for repeatable elements. In Python `xmltodict`, use `force_list=("invoice",)`. In JavaScript `fast-xml-parser`, use `isArray`.
Mistake 3: Accidentally converting IDs to numbers
XML stores text. If your converter parses values automatically, this:
```xml
may become:
```json "accountId": 456 ```
That is not the same ID. Disable automatic value parsing during conversion, then convert only known numeric fields later. Product IDs, ZIP codes, account numbers, phone numbers, and SKU values should usually stay strings.
Mistake 4: Mishandling namespaces
XML namespaces look like this:
```xml
Some converters keep prefixes in the JSON keys:
```json "soap:Envelope": { "soap:Body": { "m:GetPrice": { "m:Item": "A-100" } } } ```
That is fine if you need to rebuild the same XML. If you only need the business data, you may want to strip namespaces and extract just:
```json { "item": "A-100" } ```
Do not strip namespaces blindly when working with SOAP, finance, government, medical, or standards-based files. The receiving system may require the exact namespace URI and prefix structure.
Mistake 5: Mixed content
Mixed content means text and child elements are combined:
```xml
Please read the terms carefully.
```This does not map neatly to ordinary JSON. A converter may produce something like:
```json { "p": { "#text": "Please read the carefully.", "strong": "terms" } } ```
The original word order is partly lost unless the converter preserves node order. If your XML contains document-style content, such as articles, contracts, or formatted descriptions, test carefully. Basic XML-to-JSON conversion works best for data records, not rich text documents.
Troubleshooting checklist for real files
If the conversion fails immediately, open the XML and check the first error line. XML parsers usually stop at the first invalid character or unclosed tag. Fix that error, then run again. One broken ampersand near the top can hide many later issues.
If the JSON output is valid but the importing app rejects it, compare field names exactly. JSON keys are case-sensitive. `"CustomerID"`, `"customerId"`, and `"customerID"` are three different keys.
If the output file is huge, avoid pretty-printing for production. Pretty JSON is easier to read, but it adds whitespace. Use pretty formatting while testing, then compact JSON for transfer:
```js JSON.stringify(data) ```
instead of:
```js JSON.stringify(data, null, 2) ```
If dates change, keep them as strings during conversion. XML has no single required date format. You may see `2026-03-15`, `03/15/2026`, or `2026-03-15T14:30:00Z`. Convert dates only after you know the required target format.
If characters look wrong, confirm every step uses UTF-8: the XML declaration, your editor, your script’s file read, and your script’s file write. In Python, always pass `encoding="utf-8"` when reading and writing these files.
Practical wrap-up
The safest way to convert XML to JSON is to preserve attributes, force repeatable elements into arrays, keep values as strings at first, and test with a small sample before processing the full file. Going back from JSON to XML works well if your JSON keeps clear markers for attributes and text nodes.
If your source data is actually tabular rather than XML-based, try the BestAIFinds CSV to JSON tool first. It may give you cleaner JSON with fewer structural surprises.