A serializer walks the object graph field by field and emits each value in the chosen wire format. Text formats like JSON write human-readable characters: the number 1000000 becomes the seven characters 1000000. Binary formats like Protocol Buffers write raw bytes using compact encodings, so a small integer might fit in a single byte using variable-length encoding (varints).
Schemas matter. JSON is schemaless and self-describing, so every message repeats the field names ("userId", "createdAt") as text, which is flexible but wasteful. Protobuf and Avro use a separate schema instead. Protobuf gives each field a number, so the wire format carries field 1, field 2 instead of full names, and Avro writes the values in schema order with no field names or numbers at all. That makes the payload far smaller and parsing faster, at the cost of needing the schema to read the data.
Deserialization is where most security and performance problems hide. Parsing untrusted input can blow up memory, and formats that deserialize arbitrary types (Java native serialization, Python pickle) have caused remote code execution vulnerabilities. Treat any byte stream from outside your trust boundary as hostile and validate after parsing.