Skip to content

Commit

Permalink
[Serializer] Fix union of enum denormalization
Browse files Browse the repository at this point in the history
  • Loading branch information
mtarld committed Aug 24, 2023
1 parent f009c34 commit 96d28a5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
7 changes: 4 additions & 3 deletions Normalizer/AbstractObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down
36 changes: 36 additions & 0 deletions Tests/Normalizer/AbstractObjectNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
) {
}
}

0 comments on commit 96d28a5

Please sign in to comment.