Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0523bd3

Browse files
bug #45861 [Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false (T-bond)
This PR was squashed before being merged into the 4.4 branch. Discussion ---------- [Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #45860 | License | MIT | Doc PR | - I found a similar bug, (I think this is a bug, but it is possible, it is an intended behaviour) to my previous report. Commits ------- bd623b9 [Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false
2 parents af45ea5 + bd623b9 commit 0523bd3

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public function denormalize($data, $type, $format = null, array $context = [])
370370
}
371371
}
372372

373-
if (!empty($extraAttributes)) {
373+
if ($extraAttributes) {
374374
throw new ExtraAttributesException($extraAttributes);
375375
}
376376

@@ -405,6 +405,7 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
405405

406406
$expectedTypes = [];
407407
$isUnionType = \count($types) > 1;
408+
$extraAttributesException = null;
408409
foreach ($types as $type) {
409410
if (null === $data && $type->isNullable()) {
410411
return null;
@@ -494,9 +495,21 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
494495
if (!$isUnionType) {
495496
throw $e;
496497
}
498+
} catch (ExtraAttributesException $e) {
499+
if (!$isUnionType) {
500+
throw $e;
501+
}
502+
503+
if (!$extraAttributesException) {
504+
$extraAttributesException = $e;
505+
}
497506
}
498507
}
499508

509+
if ($extraAttributesException) {
510+
throw $extraAttributesException;
511+
}
512+
500513
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {
501514
return $data;
502515
}

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Serializer\Encoder\DecoderInterface;
2020
use Symfony\Component\Serializer\Encoder\EncoderInterface;
2121
use Symfony\Component\Serializer\Encoder\JsonEncoder;
22+
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
2223
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
2324
use Symfony\Component\Serializer\Exception\LogicException;
2425
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
@@ -31,6 +32,7 @@
3132
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
3233
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
3334
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
35+
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
3436
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
3537
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
3638
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
@@ -573,6 +575,35 @@ public function testUnionTypeDeserializable()
573575
$this->assertEquals(new DummyUnionType(), $actual, 'Union type denormalization third case failed.');
574576
}
575577

578+
public function testUnionTypeDeserializableWithoutAllowedExtraAttributes()
579+
{
580+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
581+
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
582+
$serializer = new Serializer(
583+
[
584+
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
585+
],
586+
['json' => new JsonEncoder()]
587+
);
588+
589+
$actual = $serializer->deserialize('{ "v": { "a": 0 }}', DummyUnionWithAAndB::class, 'json', [
590+
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
591+
]);
592+
593+
$this->assertEquals(new DummyUnionWithAAndB(new DummyATypeForUnion()), $actual);
594+
595+
$actual = $serializer->deserialize('{ "v": { "b": 1 }}', DummyUnionWithAAndB::class, 'json', [
596+
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
597+
]);
598+
599+
$this->assertEquals(new DummyUnionWithAAndB(new DummyBTypeForUnion()), $actual);
600+
601+
$this->expectException(ExtraAttributesException::class);
602+
$serializer->deserialize('{ "v": { "b": 1, "c": "i am not allowed" }}', DummyUnionWithAAndB::class, 'json', [
603+
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
604+
]);
605+
}
606+
576607
/**
577608
* @requires PHP 8.2
578609
*/
@@ -678,6 +709,30 @@ public function setChanged($changed): self
678709
}
679710
}
680711

712+
class DummyATypeForUnion
713+
{
714+
public $a = 0;
715+
}
716+
717+
class DummyBTypeForUnion
718+
{
719+
public $b = 1;
720+
}
721+
722+
class DummyUnionWithAAndB
723+
{
724+
/** @var DummyATypeForUnion|DummyBTypeForUnion */
725+
public $v;
726+
727+
/**
728+
* @param DummyATypeForUnion|DummyBTypeForUnion $v
729+
*/
730+
public function __construct($v)
731+
{
732+
$this->v = $v;
733+
}
734+
}
735+
681736
interface NormalizerAwareNormalizer extends NormalizerInterface, NormalizerAwareInterface
682737
{
683738
}

0 commit comments

Comments
 (0)