The core problem
The frontend is JavaScript, and the backend might be Python, Go or Rust. They can't read each other's objects from memory. So both sides agree on a common text format, JSON, to send data over the network.
No common format
Agreed format: JSON
Press ▶ Play or “Next step”. Arrow keys work too.
Debug view
Step through the diagram to see requests and responses.
Step through the diagram to see requests and responses.
What is serialization?
Serialization means turning my in-memory data into something I can send, like a JSON string. Deserialization is turning that string back into an object on the other side. In JavaScript that's JSON.stringify and JSON.parse.
Press ▶ Play or “Next step”. Arrow keys work too.
Debug view
Step through the diagram to see requests and responses.
Text vs binary formats
Text formats like JSON, XML and YAML are readable by humans but bigger. Binary formats like Protobuf are raw bytes: smaller and faster, but you can't read them without a tool. REST APIs almost always use JSON.
| Category | Examples | When used |
|---|---|---|
| Text | JSON, XML, YAML | REST APIs, config files, logs |
| Binary | Protobuf, Avro | High-performance service-to-service |
The same user, { name: "Ali", age: 25 }, in both:
JSON is the default for REST APIs. You'll rarely use XML or binary formats unless a system requires it.
{"name":"Ali","age":25}# Protobuf (schema: name = field 1, age = field 2): 7 bytes instead of 23
0a 03 41 6c 69 10 19JSON rules
Keys must be in double quotes. Values can be a string, number, true/false, null, an array or an object. No comments and no trailing commas. And a JSON document doesn't have to be an object: [1,2,3] and "hello" are valid too.
JSON playground
✓ Valid JSON. Top-level value: object
JSON.parse(text) // typeof → "object"
{
"name": "Ali",
"age": 25,
"active": true,
"skills": [
"Node",
"Postgres"
],
"address": {
"city": "Rawalpindi",
"country": "Pakistan"
}
}JSON (JavaScript Object Notation) isn't limited to JavaScript; every language reads and writes it. It's used in REST requests and responses, log files, and config files like package.json and tsconfig.json.
- A JSON document can be any JSON value: an object
{…}, an array[…], a string, a number,true/false, ornull. It doesn't have to start with{. - All keys must be strings in double quotes:
"name", notnameor'name'. - Values can only be: string, number, boolean,
null, array, or another object. - No comments.
- No trailing commas.
The backend engineer's mental model
Under the hood, my JSON gets wrapped in HTTP, split into TCP packets and routed over IP. But when it reaches the server it's exactly the same JSON string again. As a backend developer, I only work with that JSON.
Press ▶ Play or “Next step”. Arrow keys work too.
Debug view
Step through the diagram to see requests and responses.
Code: serialize and deserialize in Node
JSON.stringify turns an object into a JSON string; JSON.parse turns it back. In Express, express.json() parses every request body into req.body, and res.json() stringifies my response and sets Content-Type.
What Express does automatically:
Without Express, this is the work express.json() and res.json() hide:
const user = { name: 'Ali', age: 25 }
const jsonString = JSON.stringify(user) // SERIALIZE → '{"name":"Ali","age":25}' (string)
const jsObject = JSON.parse(jsonString) // DESERIALIZE → { name: 'Ali', age: 25 } (object)app.use(express.json()) // deserializes every JSON request body (without it, req.body is undefined)
app.post('/users', (req, res) => {
const user = req.body // already a JS object
res.status(201).json({ created: user }) // serializes + sets Content-Type: application/json
})const http = require('http')
http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/users') {
let body = ''
req.on('data', (chunk) => (body += chunk)) // collect raw chunks from the stream
req.on('end', () => {
let user
try {
user = JSON.parse(body) // manually deserialize
} catch {
res.writeHead(400, { 'Content-Type': 'application/json' })
return res.end(JSON.stringify({ error: 'invalid JSON' })) // bad JSON must not crash the server
}
res.writeHead(201, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ created: user })) // manually serialize
})
}
}).listen(3000)Quick revision
| Term | One line |
|---|---|
| Serialization | Your data into JSON before sending |
| Deserialization | JSON back into your data after receiving |
| JSON | Text-based, human-readable, the standard for REST APIs |
| Binary formats | Protobuf, Avro: smaller and faster, not human-readable |
JSON.stringify() | JS value → JSON string |
JSON.parse() | JSON string → JS value (throws on invalid input) |
express.json() | Auto-deserializes every JSON request body |
res.json() | Auto-serializes the response and sets Content-Type |
Quiz
Think of the answer first, then reveal it.
- Q1 · concept
What are serialization and deserialization?
- Q2 · concept
Why can't a JavaScript client just send its object to a Rust or Python server?
- Q3 · concept
Text vs binary formats: examples and trade-offs?
- Q4 · concept
Is
[1, 2, 3]valid JSON? What about"hello"ornull? - Q5 · scenario
What's wrong with
{ name: 'Ali', age: 25, }as JSON? - Q6 · concept
What do
express.json()andres.json()do under the hood? - Q7 · scenario
req.bodyisundefinedin your POST handler. Why? - Q8 · scenario
Your plain Node server crashes when a client sends malformed JSON. Why, and how do you fix it?
- Q9 · concept
As a backend engineer, which network layer do you work with, and why can you ignore the rest?
- Q10 · concept
Walk through the full request/response serialization flow for a form submit to Express.