JSON, XML & the Format Transition
Payload formats, Content-Type, SOAP-to-REST, and bridging legacy systems.
Learning objectives
- Compare JSON and XML as API payload formats
- Read
Content-Typeheaders and know which parser to use - Explain why JSON replaced XML for most new REST APIs — and where XML still appears
- Recognize a legacy XML/SOAP integration and plan a JSON transition
Two ways to structure data in HTTP bodies
When an API returns or accepts structured data, the bytes in the body need a format both sides understand. For decades that meant XML. Today most new APIs use JSON. Hosting teams still bump into both — especially when wiring old accounting software, RSS feeds, or enterprise tools into modern automation.
| JSON | XML | |
|---|---|---|
| Full name | JavaScript Object Notation | Extensible Markup Language |
| Looks like | {"name": "Marcus", "seats": 4} | <class seats="4">Intro</class> |
| Typical header | Content-Type: application/json | Content-Type: application/xml or text/xml |
| Common today | REST APIs, webhooks, LLM APIs, cloud panels | Legacy SOAP, RSS/Atom, sitemaps, some gov/enterprise APIs |
| Verbosity | Compact | Heavy tags and namespaces |
JSON — the default for modern APIs
JSON maps cleanly to objects in Python, PHP, JavaScript, and Go. Workshop Co.'s booking API (from the previous chapter) is typical:
{
"classes": [
{"id": "intro-wood", "title": "Intro to Woodworking", "seats_left": 4},
{"id": "box-joint", "title": "Box Joint Masterclass", "seats_left": 0}
]
}
Rules that trip up beginners:
- Keys and string values use double quotes — not single quotes
- No trailing commas after the last item in an array or object
null,true, andfalseare lowercase (not strings)- Numbers are unquoted:
4not"4"
XML — tags, attributes, and namespaces
XML wraps data in nested elements. The same class list might look like:
<?xml version="1.0" encoding="UTF-8"?>
<classes xmlns="https://workshopco.ca/schema/v1">
<class id="intro-wood">
<title>Intro to Woodworking</title>
<seats_left>4</seats_left>
</class>
<class id="box-joint">
<title>Box Joint Masterclass</title>
<seats_left>0</seats_left>
</class>
</classes>
XML strengths that kept it alive for years:
- Schema validation — XSD files define allowed structure (useful in regulated industries)
- Namespaces — mix vocabularies in one document without name collisions
- Tooling — XSLT transforms, digital signatures, enterprise middleware built around it
Downsides for everyday API work: verbose payloads, slower to hand-edit, and easy to get wrong with unclosed tags or encoding issues.
The transition — why JSON won
Between roughly 2005 and 2015, the industry shifted from SOAP/XML services to REST/JSON. The drivers were practical, not ideological:
JavaScript in the browser could parse JSON natively (JSON.parse)
Smaller payloads = less bandwidth on phones and cron jobs
curl + JSON is readable in a terminal; XML SOAP envelopes are not
AWS, Stripe, OpenAI, DNS providers — all documented with JSON examples
SOAP (Simple Object Access Protocol) wrapped XML in a rigid envelope with WSDL contract files. It worked for bank-grade integrations but felt like flying a 747 to pick up groceries. REST over HTTP with JSON bodies became the default for “call this URL, get this object back.”
Don't panic when you encounter it: sitemap.xml, RSS feeds, Microsoft legacy endpoints, some payment gateways, and older SAGE/accounting connectors. The skill is recognizing the format and using the right parser — not memorizing every tag.
Content-Type tells you what you received
Always check the response header before parsing:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"status": "ok"}
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
<response><status>ok</status></response>
Some servers mislabel bodies (JSON returned as text/plain). If parsing fails, inspect the first character: { or [ suggests JSON; < suggests XML/HTML.
Worked example — same data, two formats
Workshop Co. wants to sync class availability to a legacy newsletter tool that only accepts XML, while their new website posts JSON to a webhook.
Incoming JSON webhook (modern contact form aggregator):
POST /hooks/class-update
Content-Type: application/json
{"class_id": "intro-wood", "seats_left": 2, "updated_at": "2026-05-31T14:00:00Z"}
Outgoing XML feed (legacy partner):
<classUpdate>
<classId>intro-wood</classId>
<seatsLeft>2</seatsLeft>
<updatedAt>2026-05-31T14:00:00Z</updatedAt>
</classUpdate>
Marcus's script: json_decode() the webhook body → transform fields → build XML string (or use a small library) → POST to the partner. The translation layer is the pattern hosting teams use when bridging old and new systems.
Migration checklist — XML API to JSON
- Inventory callers — which cron jobs, plugins, or scripts still hit the XML endpoint?
- Run parallel — expose JSON alongside XML during transition; log both formats
- Map fields 1:1 — document renamed keys (
seats_leftvsseatsLeftvs<seats_left>) - Update auth — legacy SOAP often used WS-Security; JSON APIs usually use Bearer tokens (next chapter)
- Cut over — lower TTL on DNS if the endpoint hostname changes; monitor error rates for 48 hours
- Retire XML — remove WSDL/XSD docs from internal wiki once traffic hits zero
Try it yourself
Fetch Swift Host's sitemap (XML) and compare structure to a JSON API response:
curl -sI https://swifthost.ca/sitemap.xml | grep -i content-type
curl -s https://swifthost.ca/sitemap.xml | head -20
Then inspect any JSON webhook payload from a contact form (Book 8 capstone). List three structural differences you notice.
Sample differences
- XML uses opening/closing tags; JSON uses braces and commas
- XML often has a declaration line and root element; JSON starts with
{or[ - XML attributes live on tags (
loc="..."); JSON puts values in quoted key-value pairs
Quick quiz
Workshop Co.'s accountant says their old integration sends SOAP XML to a Sage connector. Marcus wants a Python script on the server instead. What is the first question he should ask the vendor?
Answer
“Is there a REST/JSON API or webhook for the same data?” Many vendors added JSON endpoints alongside legacy SOAP. If yes, skip building XML by hand. If no, plan a small translation service that accepts JSON internally and emits the required XML envelope.