From 90ffb90fc5af4be3360d9d3da9cea85b6ad59953 Mon Sep 17 00:00:00 2001 From: Rodion Kulakov Date: Mon, 1 May 2023 21:24:52 +0300 Subject: [PATCH] [Serializer] Improve denormalization of backed enums --- src/Symfony/Component/Serializer/CHANGELOG.md | 2 ++ .../Serializer/Normalizer/BackedEnumNormalizer.php | 10 ++++++---- .../Tests/Normalizer/BackedEnumNormalizerTest.php | 9 ++++++++- .../Component/Serializer/Tests/SerializerTest.php | 8 +++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 692226968f2c0..cffe3f208ad84 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -21,6 +21,8 @@ CHANGELOG * `JsonSerializableNormalizer` * `ObjectNormalizer` * `PropertyNormalizer` + * Make `BackedEnumNormalizer` throw `NotNormalizableValueException` when the backed type doesn't match + * Make `BackedEnumNormalizer` throw `NotNormalizableValueException` when the value does not belong to a backed enumeration 6.2 --- diff --git a/src/Symfony/Component/Serializer/Normalizer/BackedEnumNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/BackedEnumNormalizer.php index 32ee831c8c2df..30d4515b5791f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/BackedEnumNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/BackedEnumNormalizer.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Serializer\Normalizer; -use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; @@ -69,14 +68,17 @@ public function denormalize(mixed $data, string $type, string $format = null, ar } } - if (!\is_int($data) && !\is_string($data)) { - throw NotNormalizableValueException::createForUnexpectedDataType('The data is neither an integer nor a string, you should pass an integer or a string that can be parsed as an enumeration case of type '.$type.'.', $data, [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true); + $backingType = (new \ReflectionEnum($type))->getBackingType()->getName(); + $givenType = \get_debug_type($data); + + if ($givenType !== $backingType) { + throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Data expected to be "%s", "%s" given. You should pass a value that can be parsed as an enumeration case of type %s.', $backingType, $givenType, $type), $data, [$backingType], $context['deserialization_path'] ?? null, true); } try { return $type::from($data); } catch (\ValueError $e) { - throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type); + throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type '.$type, $data, [$backingType], $context['deserialization_path'] ?? null, true); } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/BackedEnumNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/BackedEnumNormalizerTest.php index aa0cefe0b431c..15c180d19f23f 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/BackedEnumNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/BackedEnumNormalizerTest.php @@ -86,9 +86,16 @@ public function testDenormalizeObjectThrowsException() $this->normalizer->denormalize(new \stdClass(), StringBackedEnumDummy::class); } + public function testDenormalizeBadBackingTypeThrowsException() + { + $this->expectException(NotNormalizableValueException::class); + $this->expectExceptionMessage('Data expected to be "string", "int" given. You should pass a value that can be parsed as an enumeration case of type '.StringBackedEnumDummy::class.'.'); + $this->normalizer->denormalize(1, StringBackedEnumDummy::class); + } + public function testDenormalizeBadBackingValueThrowsException() { - $this->expectException(InvalidArgumentException::class); + $this->expectException(NotNormalizableValueException::class); $this->expectExceptionMessage('The data must belong to a backed enumeration of type '.StringBackedEnumDummy::class); $this->normalizer->denormalize('POST', StringBackedEnumDummy::class); diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index c178e1b752725..d249f1645cd00 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -59,6 +59,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy; use Symfony\Component\Serializer\Tests\Fixtures\Php74Full; use Symfony\Component\Serializer\Tests\Fixtures\Php80WithPromotedTypedConstructor; +use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy; use Symfony\Component\Serializer\Tests\Fixtures\TraversableDummy; use Symfony\Component\Serializer\Tests\Fixtures\TrueBuiltInDummy; use Symfony\Component\Serializer\Tests\Fixtures\UpcomingDenormalizerInterface as DenormalizerInterface; @@ -1208,7 +1209,7 @@ public function testCollectDenormalizationErrorsWithEnumConstructor() $this->assertSame($expected, $exceptionsAsArray); } - public function testNoCollectDenormalizationErrorsWithWrongEnum() + public function testCollectDenormalizationErrorsWithWrongEnum() { $serializer = new Serializer( [ @@ -1223,8 +1224,9 @@ public function testNoCollectDenormalizationErrorsWithWrongEnum() DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, ]); } catch (\Throwable $th) { - $this->assertNotInstanceOf(PartialDenormalizationException::class, $th); - $this->assertInstanceOf(InvalidArgumentException::class, $th); + $this->assertInstanceOf(PartialDenormalizationException::class, $th); + $this->assertArrayHasKey(0, $th->getErrors()); + $this->assertSame("The data must belong to a backed enumeration of type ".StringBackedEnumDummy::class, $th->getErrors()[0]->getMessage()); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy