Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Serialization and Deserialization

Different programming languages store data in their own native formats:

  • JavaScript → Objects
  • Rust → Structs
  • Python → Dicts
  • Go → Structs These formats live in memory and are language-specific. You can’t just send a JS object over a network or any boundary to another system that wouldnt understand js object such as a rust or go server. There we agree on a neutral, language-agnostic format. Both sides can convert to/from this format. This process is called serialization and deserialization.

Serialization

This is the act of flattening your in-memory, language specific data structure into a transferrable sequence of bytes. The client converts its native data into agreed format before sending it.

const user = {
  name: "quantinium",
  age: 21,
  scores: [98, 87, 91],
  active: true
};

// Serialization → convert to a JSON string (bytes, language-agnostic)
const payload = JSON.stringify(user);
// '{"name":"quantinium","age":21,"scores":[98,87,91],"active":true}'

fetch("/api/user", {
  method: "POST",
  body: payload
});

Serialization Standards

You can use anything as a transfer format as long as both sides have a serializer and deserializer for it. Standards fall into two categories:

Text based

Human-readable, easy to debug, universally supported. Slower and larger than binary.

FormatUsed For
JSONREST APIs, web — the dominant standard
XMLEnterprise, SOAP, legacy systems
YAMLConfig files (Docker, Kubernetes, GitHub Actions)
TOMLConfig files (Cargo.toml, pyproject.toml)
CSVTabular data exports, spreadsheets

Binary

Not human-readable. Significantly smaller and faster. Used when performance matters.

FormatUsed For
ProtobufgRPC, internal microservices (by Google)
AvroKafka, data pipelines, data lakes
MessagePackReal-time apps, Redis internals, gaming
FlatBuffersGames, mobile — zero-copy deserialization

Deserialzation

The reciever get those bits and reconstructs them into its own native type.

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct User {
    name: String,
    age: u32,
    scores: Vec<u32>,
    active: bool,
}

async fn create_user(Json(user): Json<User>) -> impl IntoResponse {
    println!("{}", user.name);
}

Schema/Contract

Both sides need to agree on the shape of the data. This agreement is called a schema or contract

  • Implicit schema — both sides just follow a convention. Fragile, breaks silently.
  • Explicit schema — tools enforce the shape at the boundary.
    • Protobuf → .proto file shared between services
    • JSON Schema / OpenAPI → describes and validates JSON structure
    • Zod (TypeScript) → runtime validation on received data

Full Round Trip

CLIENT (JavaScript)                         SERVER (Rust)
───────────────────                         ─────────────

JS Object in RAM
{ name: "quantinium", age: 21 }
        │
        │ JSON.stringify()     ← SERIALIZE
        ▼
"{"name":"quantinium","age":21}"
        │
        │ HTTP POST (bytes over TCP)
        ▼
                                "{"name":"quantinium","age":21}"
                                        │
                                        │ serde_json::from_str()  ← DESERIALIZE
                                        ▼
                                User { name: "quantinium", age: 21 }
                                        │
                                        │ (process the request, build response)
                                        │
                                User { name: "quantinium", verified: true }
                                        │
                                        │ serde_json::to_string()  ← SERIALIZE
                                        ▼
                                "{"name":"quantinium","verified":true}"
                                        │
                                        │ HTTP 200 (bytes over TCP)
                                        ▼
"{"name":"quantinium","verified":true}"
        │
        │ JSON.parse()         ← DESERIALIZE
        ▼
JS Object in RAM
{ name: "quantinium", verified: true }