8000 [Serializer] Improve denormalization of backed enums · symfony/symfony@90ffb90 · GitHub
[go: up one dir, main page]

Skip to content

Commit 90ffb90

Browse files
committed
[Serializer] Improve denormalization of backed enums
1 parent 707245c commit 90ffb90

File tree

4 files changed

+21
-8
lines changed

4 files changed

+21
-8
lines changed

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ CHANGELOG
2121
* `JsonSerializableNormalizer`
2222
* `ObjectNormalizer`
2323
* `PropertyNormalizer`
24+
* Make `BackedEnumNormalizer` throw `NotNormalizableValueException` when the backed type doesn't match
25+
* Make `BackedEnumNormalizer` throw `NotNormalizableValueException` when the value does not belong to a backed enumeration
2426

2527
6.2
2628
---

src/Symfony/Component/Serializer/Normalizer/BackedEnumNormalizer.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\Serializer\Normalizer;
1313

14-
use Symfony\Component\PropertyInfo\Type;
1514
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
1615
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
1716

@@ -69,14 +68,17 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
6968
}
7069
}
7170

72-
if (!\is_int($data) && !\is_string($data)) {
73-
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);
71+
$backingType = (new \ReflectionEnum($type))->getBackingType()->getName();
72+
$givenType = \get_debug_type($data);
73+
74+
if ($givenType !== $backingType) {
75+
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);
7476
}
7577

7678
try {
7779
return $type::from($data);
7880
} catch (\ValueError $e) {
79-
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
81+
throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type '.$type, $data, [$backingType], $context['deserialization_path'] ?? null, true);
8082
}
8183
}
8284

src/Symfony/Component/Serializer/Tests/Normalizer/BackedEnumNormalizerTest.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,16 @@ public function testDenormalizeObjectThrowsException()
8686
$this->normalizer->denormalize(new \stdClass(), StringBackedEnumDummy::class);
8787
}
8888

89+
public function testDenormalizeBadBackingTypeThrowsException()
90+
{
91+
$this->expectException(NotNormalizableValueException::class);
92+
$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.'.');
93+
$this->normalizer->denormalize(1, StringBackedEnumDummy::class);
94+
}
95+
8996
public function testDenormalizeBadBackingValueThrowsException()
9097
{
91-
$this->expectException(InvalidArgumentException::class);
98+
$this->expectException(NotNormalizableValueException::class);
9299
$this->expectExceptionMessage('The data must belong to a backed enumeration of type '.StringBackedEnumDummy::class);
93100

94101
$this->normalizer->denormalize('POST', StringBackedEnumDummy::class);

src/Symfony/Component/Serializer/Tests/SerializerTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy;
6060
use Symfony\Component\Serializer\Tests\Fixtures\Php74Full;
6161
use Symfony\Component\Serializer\Tests\Fixtures\Php80WithPromotedTypedConstructor;
62+
use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy;
6263
use Symfony\Component\Serializer\Tests\Fixtures\TraversableDummy;
6364
use Symfony\Component\Serializer\Tests\Fixtures\TrueBuiltInDummy;
6465
use Symfony\Component\Serializer\Tests\Fixtures\UpcomingDenormalizerInterface as DenormalizerInterface;
@@ -1208,7 +1209,7 @@ public function testCollectDenormalizationErrorsWithEnumConstructor()
12081209
$this->assertSame($expected, $exceptionsAsArray);
12091210
}
12101211

1211-
public function testNoCollectDenormalizationErrorsWithWrongEnum()
1212+
public function testCollectDenormalizationErrorsWithWrongEnum()
12121213
{
12131214
$serializer = new Serializer(
12141215
[
@@ -1223,8 +1224,9 @@ public function testNoCollectDenormalizationErrorsWithWrongEnum()
12231224
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
12241225
]);
12251226
} catch (\Throwable $th) {
1226-
$this->assertNotInstanceOf(PartialDenormalizationException::class, $th);
1227-
$this->assertInstanceOf(InvalidArgumentException::class, $th);
1227+
$this->assertInstanceOf(PartialDenormalizationException::class, $th);
1228+
$this->assertArrayHasKey(0, $th->getErrors());
1229+
$this->assertSame("The data must belong to a backed enumeration of type ".StringBackedEnumDummy::class, $th->getErrors()[0]->getMessage());
12281230
}
12291231
}
12301232

0 commit comments

Comments
 (0)
0