diff --git a/src/SaferSerializer.php b/src/SaferSerializer.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f97268b4778e8b7783d4c93d1b48f4ace9052d1
--- /dev/null
+++ b/src/SaferSerializer.php
@@ -0,0 +1,49 @@
+<?php
+
+
+namespace Grifart\NotSerializable;
+
+
+final class SaferSerializer
+{
+
+	/**
+	 * @param mixed $dataToBeSerialized
+	 * @return string
+	 */
+	public static function serialize($dataToBeSerialized)
+	{
+		self::check($dataToBeSerialized);
+		return serialize($dataToBeSerialized);
+	}
+
+
+	/**
+	 * @param mixed $dataToBeChecked
+	 */
+	public static function check($dataToBeChecked): void
+	{
+		if (is_scalar($dataToBeChecked) || is_null($dataToBeChecked)) {
+			return;
+		}
+
+		if (!is_object($dataToBeChecked)) {
+			throw new \LogicException(\sprintf('You have passed a non-scalar, non-object value of type %s.', gettype($dataToBeChecked)));
+		}
+
+		if (! (method_exists($dataToBeChecked, '__serialize') && method_exists($dataToBeChecked, '__unserialize'))) {
+			throw new \LogicException(\sprintf('Object of type %s do NOT explicitly state serialization support using __serialize() && __unserialize() methods.', get_class($dataToBeChecked)));
+		}
+
+		// can throw exceptions, not a problem as we will call real serialize() anyway
+		$valuesToBeSerialized = $dataToBeChecked->__serialize();
+		foreach($valuesToBeSerialized as $value) {
+			self::check($value);
+		}
+
+		// as there is no way how one can check referenced properties when Serializable interface or __sleep() magic method is used,
+		// we consider them as case where class did NOT stated that is serializable.
+	}
+
+
+}
\ No newline at end of file
diff --git a/tests/SaferSerializerTest.php b/tests/SaferSerializerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7b0b86b443f6afc8b488f0dd6b653fb0b11d810
--- /dev/null
+++ b/tests/SaferSerializerTest.php
@@ -0,0 +1,70 @@
+<?php
+
+use Grifart\NotSerializable\SaferSerializer;
+use Grifart\NotSerializable\NoSerialization;
+use Tester\Assert;
+
+require __DIR__ . '/../vendor/autoload.php';
+
+class NestedSerialization {
+	private object $nested;
+	public function __construct(object $nested){$this->nested = $nested;}
+
+	/**
+	 * @return array{someKey: object}
+	 */
+	public function __serialize(): array
+	{
+		return [
+			'someKey' => $this->nested
+		];
+	}
+
+	/**
+	 * @param array{someKey: object} $data
+	 */
+	public function __unserialize(array $data): void
+	{
+		$this->nested = $data['someKey'];
+	}
+}
+
+
+// This is the case when classic serialization & SaferSerialization behaviour is different
+class SerializationNotStated {}
+
+Assert::noError(fn() => serialize(new SerializationNotStated()));
+Assert::noError(fn() => serialize(new NestedSerialization(new SerializationNotStated())));
+
+Assert::exception(fn() => SaferSerializer::serialize(new SerializationNotStated()), LogicException::class, 'Object of type SerializationNotStated do NOT explicitly state serialization support using __serialize() && __unserialize() methods.');
+Assert::exception(fn() => SaferSerializer::serialize(new NestedSerialization(new SerializationNotStated())), LogicException::class, 'Object of type SerializationNotStated do NOT explicitly state serialization support using __serialize() && __unserialize() methods.');
+
+
+
+// Now check that we did not break anything:
+
+class SerializationDisabled {
+	use NoSerialization;
+}
+
+Assert::exception(fn() => serialize(new SerializationDisabled()), LogicException::class, "The class 'SerializationDisabled' is not meant to be serialized.");
+Assert::exception(fn() => serialize(new NestedSerialization(new SerializationDisabled())), LogicException::class, "The class 'SerializationDisabled' is not meant to be serialized.");
+
+Assert::exception(fn() => SaferSerializer::serialize(new SerializationDisabled()), LogicException::class, "The class 'SerializationDisabled' is not meant to be serialized.");
+Assert::exception(fn() => SaferSerializer::serialize(new NestedSerialization(new SerializationDisabled())), LogicException::class, "The class 'SerializationDisabled' is not meant to be serialized.");
+
+
+
+class SerializationImplemented {
+	/** @return array{} */
+	public function __serialize(): array { return [];}
+	/** @param array{} $data */
+	public function __unserialize(array $data): void {}
+}
+
+Assert::noError(fn() => serialize(new SerializationImplemented()));
+Assert::noError(fn() => serialize(new NestedSerialization(new SerializationImplemented())));
+
+Assert::noError(fn() => SaferSerializer::serialize(new SerializationImplemented()));
+Assert::noError(fn() => SaferSerializer::serialize(new NestedSerialization(new SerializationImplemented())));
+