Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit bd623b9

Browse filesBrowse files
T-bondnicolas-grekas
authored andcommitted
[Serializer] Try all possible denormalization route with union types when ALLOW_EXTRA_ATTRIBUTES=false
1 parent e94f1f6 commit bd623b9
Copy full SHA for bd623b9

File tree

2 files changed

+69
-1
lines changed
Filter options

2 files changed

+69
-1
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+14-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/SerializerTest.php
+55Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.