C++
Custom serialization
Learn to write your own serialization code.
What is custom serialization?
Custom serialization means you write the serialize and deserialize methods for a struct yourself. You write and read each field in order; this gives full control over the format. It is a flexible blend of the binary and text methods.
Example: struct Point { int x; int y; void serialize(std::ofstream& ofs) const { ofs.write(...); } };. The serialize method is const because it does not modify the object. A separate deserialize(std::ifstream&) method handles reading. This approach makes it easy to add error checking and version logic to serialization.
The deserialize method
The deserialize method reads serialized data back and writes it into the object's fields. It must use the same order as serialize; if the order differs the data is read corrupted.
Example: void deserialize(std::ifstream& ifs) { ifs.read(reinterpret_cast<char*>(&x), sizeof(x)); ifs.read(reinterpret_cast<char*>(&y), sizeof(y)); }. Here serialize wrote x first, so deserialize reads x first. This match is mandatory for data integrity. The two methods work as a pair: one writes, the other reads.
Exercise Custom serialization for a Point struct
Define struct Point { int x; int y; void serialize(std::ofstream& ofs) const; };. The serialize method calls ofs.write(reinterpret_cast<const char*>(&x), sizeof(x)) and the same for y. In main create Point p{3, 4}, open an std::ofstream and call p.serialize(ofs). Read back and print std::cout << loaded.x << "," << loaded.y;.
Show example solution
#include <iostream>
#include <fstream>
struct Point {
int x;
int y;
void serialize(std::ofstream& ofs) const {
ofs.write(reinterpret_cast<const char*>(&x), sizeof(x));
ofs.write(reinterpret_cast<const char*>(&y), sizeof(y));
}
};
int main() {
Point p{3, 4};
std::ofstream ofs("point.bin", std::ios::binary);
p.serialize(ofs);
ofs.close();
Point loaded{0, 0};
std::ifstream ifs("point.bin", std::ios::binary);
ifs.read(reinterpret_cast<char*>(&loaded.x), sizeof(loaded.x));
ifs.read(reinterpret_cast<char*>(&loaded.y), sizeof(loaded.y));
ifs.close();
std::cout << loaded.x << "," << loaded.y;
return 0;
}
Test yourself
-
Complete the serialize method
void ____(std::ofstream& out) const {
out.write(reinterpret_cast<const char*>(&x), sizeof(x));
}
Show answer
void serialize(std::ofstream& out) const {
out.write(reinterpret_cast<const char*>(&x), sizeof(x));
}
-
Match each piece to its role
- void serialize(ofs) const
- Writes
- void deserialize(ifs)
- Reads
- const
- Does not modify object
- sizeof(x)
- Byte size
-
What must serialize and deserialize share?
- The same operating system
- The same field order
- The same file name
- The same compiler
Show answer
The same field order — serialize and deserialize must use the same field order.
Next lesson: Summary - Serialization