JSON to XML Converter
Send a modern API response to a system that only speaks XML. Records become row elements, you name the tags, and a key XML cannot use is rewritten rather than emitted broken.
To convert JSON to XML, paste your array of objects above. Each record becomes a row element inside a root element, both of which you name, and each field becomes a child element or an attribute. Nested objects flatten into dotted names first, and keys that are not legal XML element names are corrected with the original kept in a name attribute.
Need to rename fields before you export? Open the app
The integration is older than the API
This conversion exists because two generations of systems have to talk. The service you are pulling from returns JSON because it was built recently. The system you are feeding accepts XML because it was built a long time ago and is not going to change.
That means the bar is a document that parses on the first attempt, since the feedback loop is a rejection notice the following morning. Pretty does not matter and neither does clever structure. What matters is that nothing in the output is a surprise to a strict parser.
Tabular XML, and what that rules out
The output here is deliberately tabular: one root, one element per record, one child per field. That is not the only way to express JSON as XML, and it is the useful one for feeding a system that expects rows.
It does mean nesting is flattened rather than mirrored. "customer": { "name": "Ada" } becomes an element called customer.name, not a customer element with a name inside it. Mirroring the structure sounds more faithful and it produces a document whose shape follows your API's whims, which is exactly what a fixed schema on the other end cannot accept.
If you need genuinely nested XML mirroring a JSON tree, that is a different conversion with a different set of decisions in it, and hand-writing the transform for your specific schema will get a better result than any generic tool.
Worked example
An order response:
[
{
"order_id": "ORD-00001",
"customer": { "id": 4188, "name": "Katherine Johnson" },
"total": 2151.83,
"gift": false,
"note": null
}
]
With the root named orders and the row element named order:
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<order_id>ORD-00001</order_id>
<customer.id name="customer.id">4188</customer.id>
<customer.name name="customer.name">Katherine Johnson</customer.name>
<total>2151.83</total>
<gift>false</gift>
<note/>
</order>
</orders>
A dot is legal inside an XML element name, so the flattened names survive intact. The null note became an empty element rather than being omitted, which keeps every record the same shape.
Keys XML will not take
JSON keys can be anything, including 2024, order total and the empty string. XML element names cannot start with a digit, cannot contain a space, and cannot begin with the letters x, m, l in that order.
So names are corrected mechanically and deterministically: illegal characters become underscores, and a name that cannot start where it starts gains a leading one. 2024 becomes _2024. The original is written on each element as a name attribute, so nothing about the source is lost and a note tells you how many were affected.
Determinism matters here more than elsewhere: the recipient may have a stylesheet written against your element names, and a converter that renamed things differently between runs would break it intermittently.
Types, nulls and the things that stay text
- Numbers and booleans are written as their text, which is all XML has. A schema on the other end declares the type; the document carries the characters.
- A JSON null becomes an empty element. Omitting it would make the document's shape vary record by record, which is the first thing a validator objects to.
- A missing key in one record also becomes an empty element, because the columns are the union of all keys across all records.
- An array of objects is written as JSON text inside the element. XML has no natural tabular representation for it, and inventing one would produce a structure the recipient's schema does not describe.
- Timestamps come through exactly as written. Reformatting means choosing a timezone, and nobody in this chain has the authority to.
Frequently Asked Questions
Does it mirror my JSON nesting as nested XML?
No, it produces tabular XML: one element per record with one child per field, with nested objects flattened into dotted names. Mirroring the tree produces a document whose shape follows your API, which is what a fixed schema on the other end cannot accept.
What happens to a key XML cannot use as an element name?
It is corrected and the original is kept in a name attribute on every element. A key called 2024 becomes _2024. The correction is deterministic, so the same input always produces the same element names and a stylesheet written against them keeps working.
How is null represented?
As an empty element. Leaving the element out would make the document's shape vary from record to record, and a varying shape is the first thing a schema validator rejects.
Can I choose the root and row element names?
Both, in the options, and whatever you type is checked against the XML naming rules and corrected if it has to be. The defaults are rows and row.
What about an array inside a record?
It is written as JSON text inside the element. XML has no natural tabular form for a nested list, and inventing one would produce structure the recipient's schema does not describe and cannot validate.
Does it emit a schema?
No. A DTD or XSD belongs to the specification you were sent, and a generated one would look official while disagreeing with it. The guarantee here is a well-formed document with the element names you chose.
Feed the old system from the new one
Well formed, legal names, originals preserved, one element per record.
Back to the converter