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

Skip to content

Commit e16be83

Browse files
committed
bug #40522 [Serializer] Allow AbstractNormalizer to use null for non-optional nullable constructor parameters without default value (Pierre Rineau)
This PR was merged into the 4.4 branch. Discussion ---------- [Serializer] Allow AbstractNormalizer to use null for non-optional nullable constructor parameters without default value | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #40511 | License | MIT Serializer component AbstractNormalizer attemps to guess constructor parameters, and falls back using default values when possible. Yet, it misses one use case: nullable non-optional parameter with value not being present in incoming input, case in which null is a valid value, not the default one, yet still valid. This PR introduce a two-line fix that forcefully set null as value for missing from input non-optional nullable constructor parameters values. Commits ------- d29e433 [Serializer] AbstractNormalizer force null for non-optional nullable constructor parameter denormalization when not present in input
2 parents 5dad871 + d29e433 commit e16be83

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref
501501
$params[] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
502502
} elseif ($constructorParameter->isDefaultValueAvailable()) {
503503
$params[] = $constructorParameter->getDefaultValue();
504+
} elseif ($constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
505+
$params[] = null;
504506
} else {
505507
throw new MissingConstructorArgumentsException(sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires parameter "%s" to be present.', $class, $constructorParameter->name));
506508
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
class NullableOptionalConstructorArgumentDummy
15+
{
16+
private $foo;
17+
18+
public function __construct(?\stdClass $foo)
19+
{
20+
$this->foo = $foo;
21+
}
22+
23+
public function setFoo($foo)
24+
{
25+
$this->foo = 'this setter should not be called when using the constructor argument';
26+
}
27+
28+
public function getFoo()
29+
{
30+
return $this->foo;
31+
}
32+
}

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Serializer\Tests\Fixtures\AbstractNormalizerDummy;
1919
use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
2020
use Symfony\Component\Serializer\Tests\Fixtures\NullableConstructorArgumentDummy;
21+
use Symfony\Component\Serializer\Tests\Fixtures\NullableOptionalConstructorArgumentDummy;
2122
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorDummy;
2223
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorNormalizer;
2324
use Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorTypedArgsDummy;
@@ -118,13 +119,37 @@ public function testObjectWithStaticConstructor()
118119
}
119120

120121
public function testObjectWithNullableConstructorArgument()
122+
{
123+
$normalizer = new ObjectNormalizer();
124+
$dummy = $normalizer->denormalize(['foo' => null], NullableOptionalConstructorArgumentDummy::class);
125+
126+
$this->assertNull($dummy->getFoo());
127+
}
128+
129+
public function testObjectWithNullableConstructorArgumentWithoutInput()
130+
{
131+
$normalizer = new ObjectNormalizer();
132+
$dummy = $normalizer->denormalize([], NullableOptionalConstructorArgumentDummy::class);
133+
134+
$this->assertNull($dummy->getFoo());
135+
}
136+
137+
public function testObjectWithNullableNonOptionalConstructorArgument()
121138
{
122139
$normalizer = new ObjectNormalizer();
123140
$dummy = $normalizer->denormalize(['foo' => null], NullableConstructorArgumentDummy::class);
124141

125142
$this->assertNull($dummy->getFoo());
126143
}
127144

145+
public function testObjectWithNullableNonOptionalConstructorArgumentWithoutInput()
146+
{
147+
$normalizer = new ObjectNormalizer();
148+
$dummy = $normalizer->denormalize([], NullableConstructorArgumentDummy::class);
149+
150+
$this->assertNull($dummy->getFoo());
151+
}
152+
128153
/**
129154
* @dataProvider getNormalizer
130155
*/

0 commit comments

Comments
 (0)