Skip to content

Commit 5549493

Browse files
committed
[Serializer] Throw NotNormalizableValueException if it doesn't concern a backedEnum in construct method
1 parent c6a452d commit 5549493

File tree

5 files changed

+66
-4
lines changed

5 files changed

+66
-4
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
342342

343343
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
344344
if ($constructor) {
345+
$context['has_constructor'] = true;
345346
if (true !== $constructor->isPublic()) {
346347
return $reflectionClass->newInstanceWithoutConstructor();
347348
}
@@ -431,6 +432,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex
431432
}
432433
}
433434

435+
unset($context['has_constructor']);
436+
434437
return new $class();
435438
}
436439

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ public function denormalize($data, string $type, string $format = null, array $c
6464
try {
6565
return $type::from($data);
6666
} catch (\ValueError $e) {
67-
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
67+
if (isset($context['has_constructor'])) {
68+
throw new InvalidArgumentException('The data must belong to a backed enumeration of type '.$type);
69+
}
70+
71+
throw NotNormalizableValueException::createForUnexpectedDataType('The data must belong to a backed enumeration of type '.$type, $data, [$type], $context['deserialization_path'] ?? null, true, 0, $e);
6872
}
6973
}
7074

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\Serializer\Tests\Fixtures;
4+
5+
use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy;
6+
7+
class DummyObjectWithEnumProperty
8+
{
9+
public StringBackedEnumDummy $get;
10+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public function testDenormalizeObjectThrowsException()
115115
*/
116116
public function testDenormalizeBadBackingValueThrowsException()
117117
{
118-
$this->expectException(InvalidArgumentException::class);
118+
$this->expectException(NotNormalizableValueException::class);
119119
$this->expectExceptionMessage('The data must belong to a backed enumeration of type '.StringBackedEnumDummy::class);
120120

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

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne;
6161
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
6262
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor;
63+
use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty;
6364
use Symfony\Component\Serializer\Tests\Fixtures\FalseBuiltInDummy;
6465
use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy;
6566
use Symfony\Component\Serializer\Tests\Fixtures\Php74Full;
@@ -1230,7 +1231,51 @@ public function testCollectDenormalizationErrorsWithEnumConstructor()
12301231
/**
12311232
* @requires PHP 8.1
12321233
*/
1233-
public function testNoCollectDenormalizationErrorsWithWrongEnum()
1234+
public function testCollectDenormalizationErrorsWithWrongPropertyWithoutConstruct()
1235+
{
1236+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader());
1237+
$reflectionExtractor = new ReflectionExtractor();
1238+
$propertyInfoExtractor = new PropertyInfoExtractor([], [$reflectionExtractor], [], [], []);
1239+
1240+
$serializer = new Serializer(
1241+
[
1242+
new BackedEnumNormalizer(),
1243+
new ObjectNormalizer($classMetadataFactory, null, null, $propertyInfoExtractor),
1244+
],
1245+
['json' => new JsonEncoder()]
1246+
);
1247+
1248+
try {
1249+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumProperty::class, 'json', [
1250+
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
1251+
]);
1252+
} catch (\Throwable $e) {
1253+
$this->assertInstanceOf(PartialDenormalizationException::class, $e);
1254+
}
1255+
1256+
$exceptionsAsArray = array_map(function (NotNormalizableValueException $e): array {
1257+
return [
1258+
'currentType' => $e->getCurrentType(),
1259+
'useMessageForUser' => $e->canUseMessageForUser(),
1260+
'message' => $e->getMessage(),
1261+
];
1262+
}, $e->getErrors());
1263+
1264+
$expected = [
1265+
[
1266+
'currentType' => 'string',
1267+
'useMessageForUser' => true,
1268+
'message' => 'The data must belong to a backed enumeration of type Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy',
1269+
],
1270+
];
1271+
1272+
$this->assertSame($expected, $exceptionsAsArray);
1273+
}
1274+
1275+
/**
1276+
* @requires PHP 8.1
1277+
*/
1278+
public function testNoCollectDenormalizationErrorsWithWrongEnumOnConstructor()
12341279
{
12351280
$serializer = new Serializer(
12361281
[
@@ -1241,7 +1286,7 @@ public function testNoCollectDenormalizationErrorsWithWrongEnum()
12411286
);
12421287

12431288
try {
1244-
$serializer->deserialize('{"get": "invalid"}', DummyObjectWithEnumConstructor::class, 'json', [
1289+
$serializer->deserialize('{"get": "POST"}', DummyObjectWithEnumConstructor::class, 'json', [
12451290
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true,
12461291
]);
12471292
} catch (\Throwable $th) {

0 commit comments

Comments
 (0)
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