diff --git a/README.md b/README.md
index d26b4a9..4257dc0 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Library for work with binaries
 
 Library for basic work with binary data in PHP.
-See the sample below for more information, or check out [`CoderInterface`](./src/CoderInterface.php).
+See the examples below for more information, or check out [`CoderInterface`](./src/CoderInterface.php) and [`SerializerInterface`](./src/SerializerInterface.php).
 
 ```php
 use PetrKnap\Binary\Binary;
@@ -13,6 +13,19 @@ $decoded = Binary::decode($encoded)->base64()->zlib()->checksum()->getData();
 printf('Data was coded into `%s` %s.', $encoded, $decoded === $data ? 'successfully' : 'unsuccessfully');
 ```
 
+```php
+use PetrKnap\Binary\Binary;
+
+$data = [
+    'type' => 'image/png',
+    'data' => base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+L+U4T8ABu8CpCYJ1DQAAAAASUVORK5CYII='),
+];
+$serialized = Binary::serialize($data);
+$unserialized = Binary::unserialize($serialized);
+
+printf('Data was serialized into `%s` %s.', base64_encode($serialized), $unserialized === $data ? 'successfully' : 'unsuccessfully');
+```
+
 ---
 
 Run `composer require petrknap/binary` to install it.
diff --git a/src/Binary.php b/src/Binary.php
index 7b52b6e..6b16bfa 100644
--- a/src/Binary.php
+++ b/src/Binary.php
@@ -15,4 +15,23 @@ public static function decode(string $data): Decoder
     {
         return new Decoder($data);
     }
+
+    public static function serialize(mixed $data): string
+    {
+        return self::getSerializer()->serialize(serializable: $data);
+    }
+
+    public static function unserialize(string $data): mixed
+    {
+        return self::getSerializer()->unserialize(serialized: $data);
+    }
+
+    private static function getSerializer(): Serializer
+    {
+        static $serializer;
+        return $serializer ??= new Serializer(
+            new Encoder(),
+            new Decoder(),
+        );
+    }
 }
diff --git a/src/Coder.php b/src/Coder.php
index a304a44..362e3c0 100644
--- a/src/Coder.php
+++ b/src/Coder.php
@@ -17,10 +17,15 @@ abstract class Coder implements CoderInterface
     ];
 
     public function __construct(
-        protected readonly string $data,
+        protected readonly string $data = '',
     ) {
     }
 
+    public function withData(string $data): static
+    {
+        return static::create($this, $data);
+    }
+
     public function getData(): string
     {
         return $this->data;
diff --git a/src/CoderInterface.php b/src/CoderInterface.php
index fd324cc..80301e5 100644
--- a/src/CoderInterface.php
+++ b/src/CoderInterface.php
@@ -11,6 +11,8 @@ interface CoderInterface
 {
     public const CHECKSUM_ALGORITHM = 'crc32';
 
+    public function withData(string $data): static;
+
     public function getData(): string;
 
     /**
diff --git a/src/Exception/CouldNotSerializeData.php b/src/Exception/CouldNotSerializeData.php
new file mode 100644
index 0000000..5793f2c
--- /dev/null
+++ b/src/Exception/CouldNotSerializeData.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PetrKnap\Binary\Exception;
+
+use PetrKnap\Binary\SerializerInterface;
+use RuntimeException;
+use Throwable;
+
+final class CouldNotSerializeData extends RuntimeException implements SerializerException
+{
+    public function __construct(
+        private readonly SerializerInterface $serializer,
+        private readonly mixed $data,
+        ?Throwable $reason = null,
+    ) {
+        parent::__construct(
+            sprintf(
+                '%s could not serialize %s',
+                $serializer::class,
+                is_object($data) ? $data::class : gettype($data),
+            ),
+            previous: $reason,
+        );
+    }
+
+    public function getSerializer(): SerializerInterface
+    {
+        return $this->serializer;
+    }
+
+    public function getData(): mixed
+    {
+        return $this->data;
+    }
+}
diff --git a/src/Exception/CouldNotUnserializeData.php b/src/Exception/CouldNotUnserializeData.php
new file mode 100644
index 0000000..0449b02
--- /dev/null
+++ b/src/Exception/CouldNotUnserializeData.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PetrKnap\Binary\Exception;
+
+use PetrKnap\Binary\SerializerInterface;
+use RuntimeException;
+use Throwable;
+
+final class CouldNotUnserializeData extends RuntimeException implements SerializerException
+{
+    public function __construct(
+        private readonly SerializerInterface $serializer,
+        private readonly string $data,
+        ?Throwable $reason = null,
+    ) {
+        parent::__construct(
+            sprintf(
+                '%s could not unserialize string(%d)',
+                $serializer::class,
+                strlen($data)
+            ),
+            previous: $reason,
+        );
+    }
+
+    public function getSerializer(): SerializerInterface
+    {
+        return $this->serializer;
+    }
+
+    public function getData(): string
+    {
+        return $this->data;
+    }
+}
diff --git a/src/Exception/SerializerException.php b/src/Exception/SerializerException.php
new file mode 100644
index 0000000..40acedf
--- /dev/null
+++ b/src/Exception/SerializerException.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PetrKnap\Binary\Exception;
+
+use PetrKnap\Binary\SerializerInterface;
+
+interface SerializerException extends BinaryException
+{
+    public function getSerializer(): SerializerInterface;
+}
diff --git a/src/Serializer.php b/src/Serializer.php
new file mode 100644
index 0000000..f435a69
--- /dev/null
+++ b/src/Serializer.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PetrKnap\Binary;
+
+use Throwable;
+
+class Serializer implements SerializerInterface
+{
+    public function __construct(
+        protected readonly EncoderInterface $encoder,
+        protected readonly DecoderInterface $decoder,
+    ) {
+    }
+
+    public function serialize(mixed $serializable): string
+    {
+        try {
+            $serialized = $this->doSerialize($serializable);
+            return $this->encoder->withData($serialized)->zlib()->getData();
+        } catch (Throwable $reason) {
+            throw new Exception\CouldNotSerializeData($this, $serializable, $reason);
+        }
+    }
+
+    public function unserialize(string $serialized): mixed
+    {
+        try {
+            $serialized = $this->decoder->withData($serialized)->zlib()->getData();
+            return $this->doUnserialize($serialized);
+        } catch (Throwable $reason) {
+            throw new Exception\CouldNotUnserializeData($this, $serialized, $reason);
+        }
+    }
+
+    /**
+     * Alternative to {@see serialize()}
+     *
+     * @throws Throwable
+     */
+    protected function doSerialize(mixed $serializable): string
+    {
+        return serialize($serializable);
+    }
+
+    /**
+     * Alternative to {@see unserialize()}
+     *
+     * @throws Throwable
+     */
+    protected function doUnserialize(string $serialized): mixed
+    {
+        return unserialize($serialized);
+    }
+}
diff --git a/src/SerializerInterface.php b/src/SerializerInterface.php
new file mode 100644
index 0000000..7f9a6b7
--- /dev/null
+++ b/src/SerializerInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace PetrKnap\Binary;
+
+interface SerializerInterface
+{
+    /**
+     * {@see serialize()} the serializable
+     *
+     * @throws Exception\CouldNotSerializeData
+     */
+    public function serialize(mixed $serializable): string;
+
+    /**
+     * {@see unserialize()} the serialized
+     *
+     * @throws Exception\CouldNotUnserializeData
+     */
+    public function unserialize(string $serialized): mixed;
+}
diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php
index b3b9c86..cbeabac 100644
--- a/tests/ReadmeTest.php
+++ b/tests/ReadmeTest.php
@@ -18,7 +18,8 @@ public static function getPathToMarkdownFile(): string
     public static function getExpectedOutputsOfPhpExamples(): iterable
     {
         return [
-            'coders' => 'Data was coded into `a8vMFCssyD2Rs5BB0Evt6tJv10J_b2Aoui0tcXT69aaPP9oIyB-fLeAHAA` successfully.',
+            'coder' => 'Data was coded into `a8vMFCssyD2Rs5BB0Evt6tJv10J_b2Aoui0tcXT69aaPP9oIyB-fLeAHAA` successfully.',
+            'serializer' => 'Data was serialized into `S7QysqoutjKxUiqpLEhVsi62srRSysxNTE/VL8hLB/GBUimJJYkgpoWxlVJngJ87L5cUFwMDA6+nh0sQkGYEYQ42ICkveqQTxCkOcndiWHdO5iVYlYtjiER48o/9Ux7aM7C9Z1qixnnFBCjB4Onq57LOKaFJyboWAA==` successfully.',
         ];
     }
 }
diff --git a/tests/SerializerTest.php b/tests/SerializerTest.php
new file mode 100644
index 0000000..2e9420a
--- /dev/null
+++ b/tests/SerializerTest.php
@@ -0,0 +1,124 @@
+<?php declare(strict_types=1);
+
+namespace PetrKnap\Binary;
+
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use stdClass;
+
+final class SerializerTest extends TestCase
+{
+    private EncoderInterface&MockObject $internalEncoder;
+    private DecoderInterface&MockObject $internalDecoder;
+    private SerializerInterface&MockObject $internalSerializer;
+    private Serializer $serializer;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+
+        $this->internalEncoder = self::createMock(EncoderInterface::class);
+        $this->internalDecoder = self::createMock(DecoderInterface::class);
+        $this->internalSerializer = self::createMock(SerializerInterface::class);
+
+        $this->serializer = new class (
+            $this->internalEncoder,
+            $this->internalDecoder,
+            $this->internalSerializer,
+        ) extends Serializer {
+            public function __construct(
+                EncoderInterface $encoder,
+                DecoderInterface $decoder,
+                private readonly SerializerInterface $serializer,
+            ) {
+                parent::__construct($encoder, $decoder);
+            }
+            protected function doSerialize(mixed $serializable): string
+            {
+                return $this->serializer->serialize($serializable);
+            }
+            protected function doUnserialize(string $serialized): mixed
+            {
+                return $this->serializer->unserialize($serialized);
+            }
+        };
+    }
+
+    public function testSerializesData(): void
+    {
+        $data = new stdClass();
+        $data->array = [];
+        $data->binary = 0b0;
+        $data->float = .0;
+        $data->int = 0;
+        $data->null = null;
+        $data->string = '';
+        $serializer = new Serializer(
+            new Encoder(),
+            new Decoder(),
+        );
+
+        self::assertEquals(
+            $data,
+            $serializer->unserialize(
+                $serializer->serialize(
+                    $data,
+                ),
+            ),
+        );
+    }
+
+    public function testCallsDoSerializeAndUsesEncoder(): void
+    {
+        $serializable = (string) 0b01;
+        $serialized = (string) 0b10;
+        $encoded = (string) 0b11;
+
+        $this->internalSerializer->expects(self::once())
+            ->method('serialize')
+            ->with($serializable)
+            ->willReturn($serialized);
+        $this->internalEncoder->expects(self::once())
+            ->method('withData')
+            ->with($serialized)
+            ->willReturn($this->internalEncoder);
+        $this->internalEncoder->expects(self::once())
+            ->method('zlib')
+            ->willReturn($this->internalEncoder);
+        $this->internalEncoder->expects(self::once())
+            ->method('getData')
+            ->willReturn($encoded);
+
+        self::assertSame(
+            $encoded,
+            $this->serializer->serialize($serializable),
+        );
+    }
+
+    public function testUsesDecoderAndCallsDoUnserialize(): void
+    {
+        $serialized = (string) 0b01;
+        $decoded = (string) 0b10;
+        $serializable = (string) 0b11;
+
+        $this->internalDecoder->expects(self::once())
+            ->method('withData')
+            ->with($serialized)
+            ->willReturn($this->internalDecoder);
+        $this->internalDecoder->expects(self::once())
+            ->method('zlib')
+            ->willReturn($this->internalDecoder);
+        $this->internalDecoder->expects(self::once())
+            ->method('getData')
+            ->willReturn($decoded);
+        $this->internalSerializer->expects(self::once())
+            ->method('unserialize')
+            ->with($decoded)
+            ->willReturn($serializable);
+
+        self::assertSame(
+            $serializable,
+            $this->serializer->unserialize($serialized),
+        );
+    }
+}