Skip to content

Commit

Permalink
[Serializer] Fix denormalization union types with constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
Gwemox committed Jun 24, 2022
1 parent 31cbb3c commit bd020a5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
16 changes: 16 additions & 0 deletions Normalizer/AbstractObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
Expand Down Expand Up @@ -395,6 +396,8 @@ abstract protected function setAttributeValue($object, $attribute, $value, $form
* @return mixed
*
* @throws NotNormalizableValueException
* @throws ExtraAttributesException
* @throws MissingConstructorArgumentsException
* @throws LogicException
*/
private function validateAndDenormalize(string $currentClass, string $attribute, $data, ?string $format, array $context)
Expand All @@ -406,6 +409,7 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
$expectedTypes = [];
$isUnionType = \count($types) > 1;
$extraAttributesException = null;
$missingConstructorArgumentException = null;
foreach ($types as $type) {
if (null === $data && $type->isNullable()) {
return null;
Expand Down Expand Up @@ -503,13 +507,25 @@ private function validateAndDenormalize(string $currentClass, string $attribute,
if (!$extraAttributesException) {
$extraAttributesException = $e;
}
} catch (MissingConstructorArgumentsException $e) {
if (!$isUnionType) {
throw $e;
}

if (!$missingConstructorArgumentException) {
$missingConstructorArgumentException = $e;
}
}
}

if ($extraAttributesException) {
throw $extraAttributesException;
}

if ($missingConstructorArgumentException) {
throw $missingConstructorArgumentException;
}

if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {
return $data;
}
Expand Down
32 changes: 24 additions & 8 deletions Tests/SerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -586,20 +586,26 @@ public function testUnionTypeDeserializableWithoutAllowedExtraAttributes()
['json' => new JsonEncoder()]
);

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

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

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

$this->assertEquals(new DummyUnionWithAAndB(new DummyBTypeForUnion()), $actual);
$this->assertEquals(new DummyUnionWithAAndCAndB(new DummyBTypeForUnion()), $actual);

$actual = $serializer->deserialize('{ "v": { "c": 3 }}', DummyUnionWithAAndCAndB::class, 'json', [
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
]);

$this->assertEquals(new DummyUnionWithAAndCAndB(new DummyCTypeForUnion(3)), $actual);

$this->expectException(ExtraAttributesException::class);
$serializer->deserialize('{ "v": { "b": 1, "c": "i am not allowed" }}', DummyUnionWithAAndB::class, 'json', [
$serializer->deserialize('{ "v": { "b": 1, "d": "i am not allowed" }}', DummyUnionWithAAndCAndB::class, 'json', [
AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
]);
}
Expand Down Expand Up @@ -719,13 +725,23 @@ class DummyBTypeForUnion
public $b = 1;
}

class DummyUnionWithAAndB
class DummyCTypeForUnion
{
public $c = 2;

public function __construct($c)
{
$this->c = $c;
}
}

class DummyUnionWithAAndCAndB
{
/** @var DummyATypeForUnion|DummyBTypeForUnion */
/** @var DummyATypeForUnion|DummyCTypeForUnion|DummyBTypeForUnion */
public $v;

/**
* @param DummyATypeForUnion|DummyBTypeForUnion $v
* @param DummyATypeForUnion|DummyCTypeForUnion|DummyBTypeForUnion $v
*/
public function __construct($v)
{
Expand Down

0 comments on commit bd020a5

Please sign in to comment.