XML vs JSON
XML vs JSON
When two programs talk over a network, they cannot pass each other in-memory objects — a Python dict, a Java HashMap, and a Go struct have incompatible binary layouts. So the sender must serialize its data into a flat sequence of bytes both sides agree how to read, and the receiver parses those bytes back into its own objects. XML (eXtensible Markup Language, ~1998) and JSON (JavaScript Object Notation, ~2001) are the two dominant text-based formats for this job. They exist to solve one problem: give humans and heterogeneous machines a shared, self-describing grammar for structured data that survives crossing process, language, and machine boundaries.
Text formats win on debuggability and interoperability — you can read them in a log, curl them, diff them in code review — at the cost of size and parse speed versus binary formats. Between the two, the story is one of trade-offs: XML is a verbose, richly-typed document language; JSON is a lean data-interchange language. Knowing precisely where each wins is the interview point.
How they work, precisely
XML models a document as a tree of elements delimited by matched tags, each carrying optional attributes, plus text nodes. It ships an ecosystem: namespaces (avoid tag collisions), XML Schema (XSD) or DTD for validation, XPath to query nodes, XSLT to transform documents, and XML Signature/Encryption for element-level security. It is parsed either with DOM (whole tree in memory) or SAX/StAX (streaming, event-driven, low memory).
JSON has a much smaller grammar: four scalar types (string, number, boolean, null) and two containers (object — unordered key/value map, and array — ordered list). That maps almost 1:1 onto the native data structures of every modern language, which is why JSON.parse/Marshal are trivial. Validation is optional via JSON Schema; querying via JSONPath. Note what JSON lacks: no attributes, no comments, no namespaces, no native date type, no integer-vs-float distinction — the grammar (RFC 8259) allows arbitrary-precision numbers, but JavaScript and most parsers decode them as IEEE-754 doubles, which is where the 2^53 trap below comes from — and no built-in schema.
A concrete scenario: a public REST API at scale
Say you run an e-commerce product API serving 50,000 QPS, each response a product record. In XML the payload averages ~1.8 KB; the equivalent JSON is ~1.1 KB (roughly 35–40% smaller, mostly because JSON drops the redundant closing tag on every field). That difference compounds: 50,000 × 0.7 KB saved ≈ 35 MB/s less egress, about 3 TB/day — a direct cloud-bandwidth line item, plus lower client parse CPU and faster time-to-first-byte on mobile.
After compression — is that 3 TB/day real? Mostly no, and a staff interviewer will ask. Real APIs serve responses gzip- or brotli-compressed, and both XML and JSON are repetitive text that compresses hard — typically approximately 5–10× for payloads like these (measure on your own payloads: gzip -9 -c sample.json | wc -c). Compression squeezes out exactly the redundancy XML is guilty of (repeated tag names and closing tags), so the compressed sizes converge: the 0.7 KB-per-response gap shrinks to a small fraction of itself, and the realized egress saving is far below the uncompressed 3 TB/day headline. The honest conclusion: on the wire, compression does most of the work either way; the JSON advantages that survive compression are parse cost (the client still decompresses to the full 1.1 KB vs 1.8 KB and parses it), native browser/mobile parsing, and simpler tooling — not raw egress bytes.
On the parse side, JSON parsers (V8's native parser, simdjson reaching multiple GB/s) are dramatically faster than general XML DOM parsers, which must track namespaces and entity expansion. This is exactly why the public API surface of the 2000s (eBay, Amazon, Google) shifted from SOAP/XML to REST/JSON: browsers can parse JSON natively, and mobile clients care about every byte and millisecond. XML did not disappear — it retreated to enterprise integration (SOAP, financial FIXML/FpML, healthcare HL7, office document formats like .docx) where its schema rigor and tooling pay for themselves.
Trade-offs: when to use which
Reach for JSON when the consumer is a browser or mobile app, you are building a public REST or internal microservice API, payload size and parse speed matter, and the data is a straightforward object/array graph. It is the safe default for web-facing interchange.
Reach for XML when you need rich document structure (mixed content: text interleaved with markup, like HTML or DOCX), strong contract enforcement across organizations via XSD, namespaces to merge vocabularies, or the XPath/XSLT transformation toolchain. Regulated domains (banking FIXML/FpML, healthcare HL7v3, government/SOAP web services) standardized on XML precisely for its mature validation and signing (element-level XML Signature) — note that classic FIX itself is a terse tag=value protocol, and FIXML is its XML representation: a nice example of a domain keeping a compact wire format and an XML contract format side by side.
Named alternatives — and when they beat both:
- Protocol Buffers / Thrift / Avro (binary, schema-first): 3–10× smaller and far faster than JSON. Use for high-throughput internal service-to-service RPC (gRPC) where humans never read the wire. Cost: not human-readable, needs a compiled schema.
- MessagePack / BSON / CBOR: "binary JSON" — same data model, smaller/faster, but you lose plain-text debuggability. Good for caches and mobile sync.
- YAML / TOML: superset-ish of JSON aimed at humans writing config, not machine interchange. Comments and less punctuation, but slower and ambiguous to parse — never a wire format.
The meta-lesson: text formats (XML/JSON) trade bytes and CPU for readability and interoperability; binary formats trade readability for efficiency. Pick the axis your use case actually cares about.
Pitfalls an interviewer probes
- JSON number precision. All JSON numbers are IEEE-754 doubles, so integers above 2^53 (e.g. a 64-bit Twitter/Snowflake ID) silently lose precision in JavaScript. Fix: serialize big IDs as strings. Interviewers love this one.
- Dates. JSON has no date type — teams stuff in ISO-8601 strings or epoch millis by convention; mismatches cause bugs. XML Schema does have
xs:dateTime. - XML security: the "billion laughs" / XXE attacks. Nested entity expansion can blow up memory (DoS), and XML External Entity (XXE) injection can read local files or hit internal URLs (SSRF). Mitigation: disable DTD/external entity resolution in the parser. JSON has no entities, sidestepping this whole class.
- Attributes vs elements in XML. There is no canonical rule, so schemas drift and mapping XML to objects is lossy — a real interop headache JSON avoids.
- "JSON is always smaller/faster." Not universally: for deeply attribute-heavy data XML can be competitive, and gzip narrows the size gap sharply (both compress well since both are repetitive text). The real JSON win is native browser parsing and simpler tooling, not just raw bytes.
Key takeaways
- Same job, different weight class: both are text serialization formats for cross-language interchange; JSON is a lean data model that maps to native objects, XML is a heavyweight document language with schemas, namespaces, XPath and XSLT.
- Default to JSON for web/mobile/REST APIs (smaller, natively parsed, faster); choose XML for rich documents, cross-org contracts needing XSD validation, or regulated ecosystems (SOAP, HL7, FIXML).
- When neither fits, go binary: Protobuf/Avro/gRPC for internal high-throughput RPC, MessagePack/CBOR when you want JSON's model without the byte cost — trading human-readability for efficiency.
- Know the sharp edges: JSON's 2^53 integer precision limit and missing date type; XML's XXE / billion-laughs attacks — naming these signals real production experience.
Why binary formats are smaller and faster
Protocol Buffers, Avro, Thrift, and similar binary formats are not faster because they are mysterious; they remove text work from the wire. In JSON or XML, each object repeats key strings like "customer_id" or <customer_id>. In Protobuf, the schema assigns that field a small field number, so the wire carries a compact tag such as "field 3, wire type varint" instead of the full key string on every record. Field tags/numbers replace key strings on the wire.
Integers also use varints: small values take fewer bytes. For example, 42 fits in one byte, while a large 64-bit value expands across more bytes only when needed. Text JSON must send the ASCII digits plus separators and then parse them back into a number.
Finally, binary encodings are usually length-delimited or TLV-like: each field carries a type/wire marker and, for strings or nested messages, a byte length. That lets a parser skip unknown fields or jump over a value without scanning for quotes, escaped characters, closing tags, or matching braces. The cost is that humans cannot read the payload directly; the win is fewer bytes, less allocation, and a parser that follows schema-guided offsets instead of text grammar.
🤖 Don't fully get this? Learn it with Claude
Stuck on XML vs JSON? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **XML vs JSON** (System Design) and want to truly understand it. Explain XML vs JSON from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **XML vs JSON** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **XML vs JSON** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **XML vs JSON** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.