Format the source with the XML Formatter, then use the XML to JSON Converter to inspect attributes, repeated elements, CDATA, and nested output locally.
XML and JSON are both text representations of structured data, but they were designed around different mental models. JSON looks like the objects and arrays used in application code. XML is an ordered document tree with elements, attributes, namespaces, and text nodes. The right choice depends on the data shape and the guarantees consumers need.
1. The decision in one minute
Use JSON for new object-shaped web APIs, browser applications, and configuration that maps directly to code. Use XML when you need document-oriented markup, namespaces, XSD validation, mixed content, or compatibility with an established enterprise integration.
| Need | Usually better fit | Reason |
|---|---|---|
| REST response with objects and arrays | JSON | Direct mapping to common language types |
| Long-lived document with markup | XML | Elements, attributes, order, and mixed content |
| Multiple vocabularies | XML | Namespaces make ownership explicit |
| Small browser payload | JSON | Less syntax and common native parsers |
2. The data models are not identical
JSON has objects, arrays, strings, numbers, booleans, and null. XML has elements and attributes, plus namespaces, text nodes, comments, and declarations. An automatic XML-to-JSON mapping is therefore an opinionated design, not a universal truth.
<user id="42" role="admin">Ada</user>
{
"user": {
"@attributes": { "id": "42", "role": "admin" },
"#text": "Ada"
}
}The mapping above keeps metadata and text visible. Choose and document a convention before different teams consume the output.
3. Feature comparison
Validation
JSON Schema describes JSON values with types, required properties, patterns, and composition. XML Schema can validate elements, attributes, namespaces, order, and document constraints. A schema language helps only when the pipeline actually runs validation.
Namespaces, order, and repetition
XML namespaces prevent vocabularies from colliding. XML child order can be meaningful in a schema. JSON arrays preserve order, but object member order should not carry business meaning. Repeated XML elements should normally become arrays; a mapper that emits an object for one item and an array for many creates an unstable contract.
Comments and mixed content
XML can interleave text and child elements. Standard JSON cannot contain comments and has no mixed-content model. If markup is part of the data, flattening it may lose meaning.
4. APIs and integration
JSON is the common default for new HTTP APIs because most languages provide convenient parsers. The API still needs decisions about dates, numbers, unknown fields, errors, and pagination. XML remains important in SOAP, publishing, financial messaging, shipping, identity, and government systems.
Do not convert an XML integration merely because JSON is fashionable. Existing contracts, signatures, validators, and vendor tools may be more valuable than a smaller payload. Supporting both formats requires semantic equivalence tests, not just two serializers.
Protocol details decide how clients experience the choice. An XML API usually exposes its format through content negotiation or a versioned path, while JSON is often the implicit default. Error bodies, pagination envelopes, upload forms, and streaming responses must behave identically in whichever representation was requested, and teams that only exercise one side discover the asymmetries in production. Section 11 treats both representations as one contract under test.
5. A safe migration
- Inventory namespaces, attributes, CDATA, mixed content, repeated elements, comments, and empty tags.
- Write a mapping document with examples for every special case.
- Choose stable names for attributes and text, such as
@attributesand#text. - Define whether one element and many elements always become an array.
- Preserve namespace URIs when local names can collide.
- Compare semantic values in fixtures rather than only comparing pretty-printed text.
- Run original XML validation and new JSON validation during the transition.
The local converter is useful for inspecting structure without uploading a payload. It is not a replacement for contract tests.
6. Conversion failure modes
- Attributes disappear: the mapper emits child elements only.
- Repeated elements change shape: one item becomes an object while many become an array.
- Text nodes are lost: mixed content needs an explicit text key.
- Namespaces collide: prefixes can differ while URIs are equal, or match while URIs differ.
- Empty elements change meaning: empty string, null, missing, and empty object are different values.
- Numbers become strings: XML text has no JSON number type without a rule or schema.
- Indentation becomes content: whitespace-only text nodes between elements show up as stray
#textentries unless the mapper deliberately drops them.
Test a representative payload, an empty payload, repeated records, and an optional field. Most mapping bugs hide in those cases.
7. Where each format lives today
No format wins everywhere, and in most projects the surrounding ecosystem decides before anyone debates syntax. Validators, signatures, feeds, office documents, and vendor SDKs come in a format already; joining that world usually matters more than personal preference.
| Domain | Format | Why it stuck |
|---|---|---|
| Browser and mobile APIs | JSON | Parsers ship with the platform, and object syntax matches application code |
| SOAP and WS-* services | XML | Envelopes, WS-Security, and XML signatures are defined over XML documents |
| Syndication feeds | XML | RSS and Atom are established vocabularies with decades of reader support |
| Vector graphics and documents | XML | SVG, XHTML, DocBook, DITA, EPUB, and Office Open XML are XML formats |
| Identity and federation | XML | SAML assertions and XML Digital Signatures depend on canonical XML |
| Build and project files | Both | Maven and MSBuild projects are XML; npm, tsconfig, and most CLI tools use JSON or JSONC |
| Contracts with schemas | Both | XSD tooling is deep in finance, telecom, and government; JSON Schema dominates web API tooling |
Two forces shaped this split. JSON became a browser native: JSON.parse ships with every runtime, and its syntax is close to how developers already write object literals, so the friction of using it approached zero. XML stayed dominant wherever documents, namespaces, and validation are the point rather than the payload. Note that HTML itself is not XML — browsers parse broken HTML forgivingly, while the SVG embedded in that same page must be strict XML. Fluency with one does not transfer automatically to the other.
SOAP versus REST is a separate axis. SOAP messages are XML documents mandated by the WS-* stack; REST is an architectural style that most teams implement with JSON but can serve as XML through content negotiation without changing the resource design. The parallel choice among JSON, YAML, and TOML for configuration is covered in TOML Format Explained.
8. Attributes versus elements: a mapping that survives
XML lets you place the same information in an attribute or a child element. JSON objects have only one kind of member, so every conversion makes a design decision on the client's behalf — one that outlives the mapper that made it.
<order id="8821" currency="USD">
<customer priority="gold">Ada</customer>
<item sku="A-1">Widget</item>
<item sku="B-7">Gadget</item>
<note>Leave at door</note>
</order>| Constraint | Attributes | Child elements |
|---|---|---|
| Repetition | At most one per element | Unlimited |
| Nested structure | Not allowed; values are strings only | Can contain whole subtrees |
| Mixed content | Impossible | Required when text and markup interleave |
| Order | Unordered | Document order, sometimes schema-significant |
| Metadata such as IDs and flags | Natural fit | Works, but wordier |
| Appears in rendered text | No | Yes |
Three mapping conventions dominate, and each has a predictable failure mode:
- Namespaced keys. Attributes land under an
@attributesobject (or an@prefix) and element text under#text. Verbose, but nothing collides and the original document stays reconstructable. - Flattening. Attributes become ordinary keys beside element-derived keys. Compact, but
<x id="1"><id>2</id></x>shows the risk: the attribute and the element fight over one JSON key, and after conversion nobody can tell which produced the value. - Element-first. Elements become keys while attributes are nested or dropped. Common in quick converters; dropping attributes destroys metadata, so this convention must never become a public contract.
Three further details are visible only if you know the XML infoset. CDATA does not survive parsing — <note><![CDATA[a < b]]></note> and the escaped equivalent yield the same string, so JSON has no way to express the distinction. Entity references are decoded before mapping, and custom DTD entities should stay disabled in parsers because they enable expansion attacks. Empty elements are unambiguous in XML — <note/> and <note></note> are the same value — so a mapper that turns one into "" and the other into null is inventing a difference that was never on the wire. Pick one convention, write it into the contract with before-and-after examples, and run real payloads through the XML to JSON Converter so the mapping you document is the mapping you ship.
9. Size, parsing, and performance in practice
"XML is bulky, JSON is fast" is a half-truth that dissolves once syntax cost and parser strategy are measured separately.
Syntax overhead. Every XML element pays for a closing tag and repeats its name twice, while JSON quotes each key once per record. For object-shaped data, expect minified JSON to land roughly 1.5 to 3 times smaller than element-heavy XML; attribute-based XML narrows the gap because attributes avoid the second name occurrence. After gzip or Brotli the difference usually collapses to single-digit percentages, since repeated tag names and keys compress extremely well. Transfer size alone rarely decides the format — round-trip latency and parsing cost usually do.
Parsing. A DOM parser materializes the whole tree: convenient, and memory-hungry, because common implementations need several times the document size in RAM. Streaming XML parsers — SAX, StAX, and pull parsers — process events with constant memory and emit records before the file ends, which is why exporters and multi-gigabyte feeds still use them. JSON is normally parsed in one pass into a full object graph: fast, but proportional to the decoded result. Line-delimited and incremental JSON parsers exist for very large streams; the line-oriented variant is worth inspecting with the JSONL to JSON Converter.
| Strategy | Memory | First result | Typical fit |
|---|---|---|---|
| XML DOM | Several times the document | After full parse | Small documents needing random access |
| XML streaming | Constant | Per record | Large files, exports, feeds |
| JSON full parse | Proportional to the object graph | After full parse | Ordinary API payloads |
| JSON line-delimited | Constant | Per line | Logs and event streams |
Type conversion. XML text is untyped at parse time, so numbers, dates, and booleans must be coerced afterwards. Without a schema or a documented rule the mapper guesses: is "007" a number, is "1.0" an integer, does "2026-08-29" carry a timezone? Those guesses are where silent corruption starts. Fix the parser strategy before benchmarking, normalize both sides with the XML Formatter and JSON Formatter, and measure with production-shaped payloads rather than toy examples.
10. XSD versus JSON Schema: what each can express
Both schema languages check types, patterns, and required fields, but they target different data models, and the differences surface exactly at the edges of a migration.
| Capability | XML Schema (XSD 1.0/1.1) | JSON Schema (2020-12) |
|---|---|---|
| Data model | Elements, attributes, text, namespaces | JSON values only: object, array, string, number, boolean, null |
| Member order | xs:sequence can enforce it | Object member order carries no meaning |
| Namespaces | First-class via targetNamespace and import | None; $id and $ref play an analogous role for vocabularies |
| Attributes | xs:attribute with use, defaults, and fixed values | No attributes; they must be modeled as properties |
| Occurrence | minOccurs / maxOccurs | required, minItems, maxProperties |
| Scalar types | xs:date, xs:decimal, xs:duration, anyURI, QName | String plus pattern; format is an annotation by default |
| Identity constraints | xs:unique, xs:key, xs:keyref | No native uniqueness across arrays |
| Composition | xs:include, xs:import, xs:redefine | $ref, allOf, anyOf, oneOf, if/then/else |
| Assertions | XSD 1.1 assertions written in XPath | Conditional schemas plus custom vocabularies |
| Regular expressions | XML Schema regex flavor | ECMA-262 |
| Tooling depth | Mature enterprise and WS-* tooling | Browser, API, and code-generation tooling |
Two consequences matter in practice. First, format: "date-time" is annotation-only unless the validator is configured to enforce it, while xs:date rejects malformed values by default — a JSON pipeline can accept documents an XML pipeline would reject. Second, no JSON Schema keyword can see attributes or element order, so validating the mapped JSON proves the JSON shape, not the original document. During a migration keep the XSD running beside a JSON Schema for the mapped output; the mechanics are covered in the JSON Schema validation guide, and the mapped side is enforced in CI with the JSON Schema Validator.
11. Testing a dual-format API
Two serializations mean one semantic contract with two wire representations. Tests that compare bytes pass on formatting and fail on meaning — occasionally the other way around.
Fixture matrix. Cover the states where mappers break: a full happy-path payload; an empty payload; repeated elements with one item and with many; optional fields absent; explicit JSON null beside empty XML elements; Unicode text and entities; deep nesting; large identifiers and dates; and payloads carrying unknown extra fields.
Semantic equivalence. Convert the XML fixture with your own mapper, parse the JSON fixture, normalize both — stable key order, one empty-value policy — and assert deep equality:
const fromXml = normalize(xmlToJson(parseXml(xmlFixture)));
const fromJson = normalize(JSON.parse(jsonFixture));
assert.deepStrictEqual(fromXml, fromJson);Round trips are not byte-exact. XML converts back with different attribute order, quote style, whitespace, and empty-element form, so compare parsed trees or canonicalized output (C14N) instead of text. JSON has no official canonical form, so define one for tests — sorted keys, fixed number formatting, no insignificant whitespace — and apply it to both representations before comparing.
Validation in CI. Run XSD validation for XML fixtures and JSON Schema validation for JSON fixtures on every change. Produce stable golden files with the XML Formatter and JSON Formatter, and check hand-written edge cases with the JSON Validator before they become fixtures.
Hostile input. Malformed XML must fail closed: disable DTD processing and external entity resolution so entity-expansion and XXE payloads never execute. Malformed JSON must fail with an equivalent surface — the same status code, the same error body shape, and the same log line regardless of which format the client sent.
# illustrative CI steps — adjust tools to your stack
xmllint --noout --schema contract/order.xsd fixtures/*.xml
ajv validate -s contract/order.schema.json -d "fixtures/*.json"
node scripts/equivalence.test.mjs12. When teams regret switching
Regret is rarely about syntax. It is about capabilities the team did not know it was consuming.
After moving XML to JSON:
- Validation quietly vanished. The XSD stopped running and no JSON Schema replaced it, so malformed payloads now reach business logic.
- Namespaces became naming conventions. Prefixes and casing rules replace namespace URIs, and vocabularies that never collided start sharing keys.
- Mixed content was flattened. Documents with interleaved text and markup came back scrambled because the mapper had no text-node policy.
- The contract doubled. Partners still on SOAP or signed XML meant keeping both formats, both test suites, and both transformations — the promised simplification became parallel maintenance.
- Signatures stopped applying. XML Digital Signatures cover a canonicalized XML document; equivalent guarantees over JSON need a different, deliberately designed scheme.
After moving JSON to XML: teams pay namespace ceremony and XSD tooling for data that was always object-shaped, and every consumer must run an XML stack it would not otherwise need. The data did not become more structured; only its encoding did.
Decision checklist. Answer these in writing before migrating: Do consumers need mixed content, ordering semantics, or namespaces? Is an XSD already part of the contract? Are standards in play — SOAP, feeds, Office documents, SAML? Does the payload map cleanly onto objects and arrays? Will schema validation run in CI for both formats? Can the two formats coexist only during a transition, with equivalence tests proving they agree? If the answers point in one direction, the decision stops being about which syntax looks cleaner.
Conclusion
JSON is usually simplest for new object-shaped APIs. XML remains better when document structure, namespaces, validation, or ecosystem compatibility are central. Select based on the contract and its consumers, then document any mapping between formats.
Frequently Asked Questions
- Is JSON better than XML?
- Not universally. JSON is simpler for object-shaped APIs; XML is stronger for documents, namespaces, and established schema workflows.
- Can XML attributes become JSON fields?
- Yes, but define a stable mapping such as an @attributes object.
- Does JSON support comments?
- Standard JSON does not support comments.
- When should I keep XML?
- Keep it when consumers need XSD, namespaces, mixed content, or XML-specific tooling.
- Does XML preserve ordering?
- XML is an ordered document tree; JSON arrays preserve order, but object member order should not carry meaning.
- Is conversion lossless?
- Not automatically. Attributes, namespaces, mixed content, and repeated elements require explicit handling.
- Is XML slower to parse than JSON?
- Neither format is inherently slower. Streaming XML parsers handle huge documents in constant memory, while a full JSON parse builds the entire object graph; benchmark the parser strategy you actually ship.
- Can attributes and elements be used interchangeably?
- No. Attributes cannot repeat, cannot contain markup, and hold only strings; elements can nest, repeat, and carry schema-typed content. Choose one mapping and document it before clients depend on it.