diff --git a/Normalizer/AbstractObjectNormalizer.php b/Normalizer/AbstractObjectNormalizer.php index 5187955dd..171742616 100644 --- a/Normalizer/AbstractObjectNormalizer.php +++ b/Normalizer/AbstractObjectNormalizer.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Serializer\Normalizer; -use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; +use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException as PropertyAccessInvalidArgumentException; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; @@ -21,6 +21,7 @@ use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Exception\ExtraAttributesException; +use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; @@ -387,7 +388,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar try { $this->setAttributeValue($object, $attribute, $value, $format, $attributeContext); - } catch (InvalidArgumentException $e) { + } catch (PropertyAccessInvalidArgumentException $e) { $exception = NotNormalizableValueException::createForUnexpectedDataType( sprintf('Failed to denormalize attribute "%s" value for class "%s": '.$e->getMessage(), $attribute, $type), $data, @@ -562,7 +563,7 @@ private function validateAndDenormalize(array $types, string $currentClass, stri if (('is_'.$builtinType)($data)) { return $data; } - } catch (NotNormalizableValueException $e) { + } catch (NotNormalizableValueException|InvalidArgumentException $e) { if (!$isUnionType) { throw $e; } diff --git a/Tests/Normalizer/AbstractObjectNormalizerTest.php b/Tests/Normalizer/AbstractObjectNormalizerTest.php index 361f8520d..61345a414 100644 --- a/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -37,6 +37,7 @@ use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; +use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; @@ -769,6 +770,23 @@ public function supportsNormalization(mixed $data, string $format = null, array $this->assertSame('called', $object->bar); } + + public function testDenormalizeUnionOfEnums() + { + $serializer = new Serializer([ + new BackedEnumNormalizer(), + new ObjectNormalizer( + classMetadataFactory: new ClassMetadataFactory(new AnnotationLoader()), + propertyTypeExtractor: new PropertyInfoExtractor([], [new ReflectionExtractor()]), + ), + ]); + + $normalized = $serializer->normalize(new DummyWithEnumUnion(EnumA::A)); + $this->assertEquals(new DummyWithEnumUnion(EnumA::A), $serializer->denormalize($normalized, DummyWithEnumUnion::class)); + + $normalized = $serializer->normalize(new DummyWithEnumUnion(EnumB::B)); + $this->assertEquals(new DummyWithEnumUnion(EnumB::B), $serializer->denormalize($normalized, DummyWithEnumUnion::class)); + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -1186,3 +1204,21 @@ public function __sleep(): array throw new \Error('not serializable'); } } + +enum EnumA: string +{ + case A = 'a'; +} + +enum EnumB: string +{ + case B = 'b'; +} + +class DummyWithEnumUnion +{ + public function __construct( + public readonly EnumA|EnumB $enum, + ) { + } +}