diff --git a/src/Support/Normalization/SelfSerializingNormalizer.php b/src/Support/Normalization/SelfSerializingNormalizer.php index 1c66aab3..56eb2eb5 100644 --- a/src/Support/Normalization/SelfSerializingNormalizer.php +++ b/src/Support/Normalization/SelfSerializingNormalizer.php @@ -28,6 +28,10 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a return $data; } + if (isset($data['fqcn']) && is_a($data['fqcn'], SerializedByVerbs::class, true)) { + $type = $data['fqcn']; + } + return $type::deserializeForVerbs($data, $this->serializer); } diff --git a/tests/Feature/SerializationTest.php b/tests/Feature/SerializationTest.php index 9f6ccb09..e4f682ad 100644 --- a/tests/Feature/SerializationTest.php +++ b/tests/Feature/SerializationTest.php @@ -169,6 +169,34 @@ public function __construct() ->and($deserialized_event->dtos[0])->toBeInstanceOf(DTO::class); }); +it('allows us to store a serializable class interface as a property', function () { + $original_event = new EventWithDtoInterface; + + $serialized_data = app(Serializer::class)->serialize($original_event); + + expect($serialized_data)->toBe('{"dto":{"fqcn":"OtherDTO","bar":2}}'); + + $deserialized_event = app(Serializer::class)->deserialize(EventWithDtoInterface::class, $serialized_data); + + expect($deserialized_event->dto) + ->toBeInstanceOf(OtherDTO::class) + ->bar->toBe(2); +}); + +it('allows us to store a serializable class as a union type property', function () { + $original_event = new EventWithUnionType; + + $serialized_data = app(Serializer::class)->serialize($original_event); + + expect($serialized_data)->toBe('{"dto":{"fqcn":"OtherDTO","bar":2}}'); + + $deserialized_event = app(Serializer::class)->deserialize(EventWithUnionType::class, $serialized_data); + + expect($deserialized_event->dto) + ->toBeInstanceOf(OtherDTO::class) + ->bar->toBe(2); +}); + class EventWithConstructorPromotion extends Event { public function __construct( @@ -194,11 +222,34 @@ class DTO implements SerializedByVerbs public int $foo = 1; } +interface DTOInterface extends SerializedByVerbs {} + +class OtherDTO implements DTOInterface +{ + use NormalizeToPropertiesAndClassName; + + public int $bar = 2; +} + class EventWithDto extends Event { public DTO $dto; } +class EventWithDtoInterface extends Event +{ + public function __construct( + public DTOInterface $dto = new OtherDTO, + ) {} +} + +class EventWithUnionType extends Event +{ + public function __construct( + public DTO|OtherDTO $dto = new OtherDTO, + ) {} +} + class EventWithConstructor extends Event { public bool $constructed = false;