1. Introduction
Imagine your object in the program is like a complex, beautiful LEGO build. It's made of many pieces, each in its place, forming a single whole. While the build sits on your desk (in the computer's memory), everything is fine. But what if you need to take it to a friend (send over the network), or just put it in a box until next time (save to disk)? You can't just drop it into a flat box — it'll break apart!
That's exactly what serialization is about — carefully taking the object apart for safe storage or transfer. It's the process of converting your in-memory "live" object into a sequence of bytes (or a textual representation) that can be saved to a file, sent over the network, or put in the clipboard. Essentially, it's like disassembling your LEGO build carefully, putting pieces into labeled bags, and packing them into a box for transport or storage.
flowchart LR
ObjectInMemory(Object in memory)
Serialize[SERIALIZATION]
BytesOrText[Bytes / Text file / JSON / XML]
Deserialize[DESERIALIZATION]
ObjectAgain(Object back in memory)
ObjectInMemory -->|serialize| Serialize
Serialize --> BytesOrText
BytesOrText -->|deserialize| Deserialize
Deserialize --> ObjectAgain
And of course, if we packed something up, we must be able to unpack it! The reverse process is called deserialization. That's when you take the box with the bags of LEGO parts, dump them out, and then, following the instructions (or just remembering how it was assembled), restore the object in memory to exactly the same state it was in before packing. That's the magic!
The term "serialization" literally means "making sequential". We take a complex, possibly fragmented in-memory structure (an object may reference other objects, collections, etc., forming an entire "object graph") and turn it into a linear, sequential form that's easy to write or transmit.
2. Why isn't a simple File.WriteAllText enough?
Great question! If all data were simple strings or numbers, we could do without serialization. But in the real world our apps work with complex models: customers, orders, products, students, heroes, levels. All of these are objects in memory. That's why serialization is your best friend:
Saving application state
Imagine you're building a text editor. The user types text, changes fonts, inserts images. All this data (text, settings, cursor position) is essentially objects in your program. When the user clicks "Save", you want them to see everything exactly as they left it the next time they open the app. Serialization lets you "freeze" the necessary objects and write them to disk, then "unfreeze" them on load. It's like the "save game" feature in video games. You don't want to replay the whole level if the power went out, right?
Data exchange between applications
Your C# program may talk to a web server written in Python. Or your mobile app (for example, on Xamarin or MAUI) talks to a .NET server. Those programs don't share memory. To exchange data they need a common, understandable format. Serialization converts objects into that common format (for example, JSON or XML) which can be sent over the network. On the other side, the receiver deserializes the data back into objects that are meaningful for their programming language. Without serialization you'd have to manually unpack every piece of data and reconstruct it. That would be slow, tedious, and error-prone!
Imagine sending a package to another country. You can't just send your stuff as-is; you must pack it into a container (serialization) following international standards. At the other end the recipient can open that container and get their stuff (deserialization).
Application configuration
Apps often have many settings: window size, file paths, recently opened documents, color scheme. Storing each setting in a separate variable and then manually saving them to a config file (for example, .ini or .txt) is inefficient and inconvenient. It's way easier to define a class AppSettings where each setting is a property, and then just serialize that settings object to a file. On startup — deserialize it. Beautiful!
Data caching
Sometimes fetching data (for example, from a database or remote server) takes a long time. To avoid requesting it every time you can fetch once, serialize it and store it in a cache (on disk or in a special store). On subsequent requests you check the cache first, and if the data is there you simply deserialize it. This speeds up the app and reduces load on external data sources.
3. The main idea: saving "state"
The key concept in serialization is saving state. An object is essentially the collection of its fields and their values at a given moment. Serialization "photographs" that state. When we deserialize an object we don't just create a new empty instance; we recreate it with all the field values it had at the moment of serialization.
This isn't just copying data. It's a deep copy of structure and values, including references to other objects if the serializer supports them. Some serializers can even save type information, allowing deserialization back into the correct class even if we don't know the exact type at deserialization time.
Classic example: serializing pets
Let's continue building our "Pet Encyclopedia" app. Suppose we have this class:
public class Pet
{
public string Name { get; set; }
public string Type { get; set; } // For example: "Cat", "Dog"
public int Age { get; set; }
}
We want to:
- Fill a collection of such objects in memory,
- Save it to a file,
- And later restore it (for example, after the program restarts).
Scheme-wise it looks like this:
Collection List<Pet>
↓ serialization
File (JSON, XML, bytes)
↓ deserialization
Collection List<Pet> (back in memory!)
4. Serialization formats
Just like in shipping where there are different container types (cardboard boxes, wooden crates, metal containers), in programming there are various serialization formats. Each has its own characteristics, pros and cons.
We won't dive deep into them yet, but remember a few names so you know what's coming in future lectures:
- JSON (JavaScript Object Notation): Probably the most popular format today. It's textual, relatively human-readable, and widely used for data exchange on the web. It looks like "key-value" pairs inside curly braces. Essentially it's plain text structured so programs can easily parse it.
- XML (Extensible Markup Language): Older but still common. It's a textual format based on tags like HTML and has a strict structure. Often used for config files and enterprise data exchange. It's readable but can be verbose.
- Binary formats: These store data as raw bytes, like they're in memory. They're usually more compact and faster to (de)serialize, but unreadable to humans. Used where performance or minimal size matters, e.g., saving game state or sending large volumes of data between components of the same system.
The choice of format depends on the task: does a human need to read the data? Are speed and size important? What platforms are you communicating with? For cross-system data exchange JSON and XML are often preferred for their universality. For internal storage within the same program, binary formats can be faster and more efficient.
As you can see, serialization is a powerful tool underlying many modern apps. It lets programs "remember" their data between runs, talk to each other, and manage complex info efficiently. In the next lectures we won't just talk about the "magic" — we'll learn to apply it ourselves using .NET libraries! Get ready, it's going to be fun!
GO TO FULL VERSION