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)
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