Objects in your program have a well defined memory layout, imposed by your compiler. But that layout is not going to be exactly the same in another program, running on another machine, compiled by a different compiler. And it is not typically very compatible with the transport medium, like a network connection or a file. Which you need to take care of to get the object from one machine to another.
Files and network packets are simple streams of bytes. That's where serialization comes into play, you'll need to serialize the in-memory object into a stream of bytes. And it needs to be de-serialized at the receiving end, back from a stream of bytes into an object.
The obvious way to do so is binary serialization. You take the bytes for each field in the object and write them to the stream. Very efficient, but also very troublesome. The first problem you run into is that the receiving end has a different idea of what the object looks like. It might be compiled with a different version of the object declaration, one that had an added field for example. The problem is starker when the object is exchanged between different machines. They may have a very different idea about the number of bytes in an integer. Or the order of the bytes (endian-ness).
There have been many solutions to this problem. They typically involve some kind of metadata that describes the fields in the object. The advent of Unicode made it possible to put both the metadata and the field values into a textual description, XML is the best example of this.