diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 692226968f2c..cffe3f208ad8 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 32ee831c8c2d..30d4515b5791 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 aa0cefe0b431..15c180d19f23 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 c178e1b75272..d249f1645cd0 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()); } }
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: