Skip to content

Commit 60bc6cd

Browse files
committed
[Serializer] Fix denormalization union type with constructor
1 parent 12c6dbf commit 60bc6cd

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Serializer\Encoder\XmlEncoder;
2121
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
2222
use Symfony\Component\Serializer\Exception\LogicException;
23+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
2324
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
2425
use Symfony\Component\Serializer\Exception\RuntimeException;
2526
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
@@ -395,6 +396,8 @@ abstract protected function setAttributeValue($object, $attribute, $value, $form
395396
* @return mixed
396397
*
397398
* @throws NotNormalizableValueException
399+
* @throws ExtraAttributesException
400+
* @throws MissingConstructorArgumentsException
398401
* @throws LogicException
399402
*/
400403
private function validateAndDenormalize(string $currentClass, string $attribute, $data, ?string $format, array $context)
@@ -406,6 +409,7 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
406409
$expectedTypes = [];
407410
$isUnionType = \count($types) > 1;
408411
$extraAttributesException = null;
412+
$missingConstructorArgumentException = null;
409413
foreach ($types as $type) {
410414
if (null === $data && $type->isNullable()) {
411415
return null;
@@ -503,13 +507,25 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
503507
if (!$extraAttributesException) {
504508
$extraAttributesException = $e;
505509
}
510+
} catch (MissingConstructorArgumentsException $e) {
511+
if (!$isUnionType) {
512+
throw $e;
513+
}
514+
515+
if (!$missingConstructorArgumentException) {
516+
$missingConstructorArgumentException = $e;
517+
}
506518
}
507519
}
508520

509521
if ($extraAttributesException) {
510522
throw $extraAttributesException;
511523
}
512524

525+
if ($missingConstructorArgumentException) {
526+
throw $missingConstructorArgumentException;
527+
}
528+
513529
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {
514530
return $data;
515531
}

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

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -586,20 +586,26 @@ public function testUnionTypeDeserializableWithoutAllowedExtraAttributes()
586586
['json' => new JsonEncoder()]
587587
);
588588

589-
$actual = $serializer->deserialize('{ "v": { "a": 0 }}', DummyUnionWithAAndB::class, 'json', [
589+
$actual = $serializer->deserialize('{ "v": { "a": 0 }}', DummyUnionWithAAndCAndB::class, 'json', [
590590
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
591591
]);
592592

593-
$this->assertEquals(new DummyUnionWithAAndB(new DummyATypeForUnion()), $actual);
593+
$this->assertEquals(new DummyUnionWithAAndCAndB(new DummyATypeForUnion()), $actual);
594594

595-
$actual = $serializer->deserialize('{ "v": { "b": 1 }}', DummyUnionWithAAndB::class, 'json', [
595+
$actual = $serializer->deserialize('{ "v": { "b": 1 }}', DummyUnionWithAAndCAndB::class, 'json', [
596596
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
597597
]);
598598

599-
$this->assertEquals(new DummyUnionWithAAndB(new DummyBTypeForUnion()), $actual);
599+
$this->assertEquals(new DummyUnionWithAAndCAndB(new DummyBTypeForUnion()), $actual);
600+
601+
$actual = $serializer->deserialize('{ "v": { "c": 3 }}', DummyUnionWithAAndCAndB::class, 'json', [
602+
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
603+
]);
604+
605+
$this->assertEquals(new DummyUnionWithAAndCAndB(new DummyCTypeForUnion(3)), $actual);
600606

601607
$this->expectException(ExtraAttributesException::class);
602-
$serializer->deserialize('{ "v": { "b": 1, "c": "i am not allowed" }}', DummyUnionWithAAndB::class, 'json', [
608+
$serializer->deserialize('{ "v": { "b": 1, "d": "i am not allowed" }}', DummyUnionWithAAndCAndB::class, 'json', [
603609
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
604610
]);
605611
}
@@ -719,13 +725,23 @@ class DummyBTypeForUnion
719725
public $b = 1;
720726
}
721727

722-
class DummyUnionWithAAndB
728+
class DummyCTypeForUnion
729+
{
730+
public $c = 2;
731+
732+
public function __construct($c)
733+
{
734+
$this->c = $c;
735+
}
736+
}
737+
738+
class DummyUnionWithAAndCAndB
723739
{
724-
/** @var DummyATypeForUnion|DummyBTypeForUnion */
740+
/** @var DummyATypeForUnion|DummyCTypeForUnion|DummyBTypeForUnion */
725741
public $v;
726742

727743
/**
728-
* @param DummyATypeForUnion|DummyBTypeForUnion $v
744+
* @param DummyATypeForUnion|DummyCTypeForUnion|DummyBTypeForUnion $v
729745
*/
730746
public function __construct($v)
731747
{

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