diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 6442e98a1473..aa72e9d49e12 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -351,6 +351,11 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref } } catch (\ReflectionException $e) { throw new RuntimeException(sprintf('Could not determine the class of the parameter "%s".', $key), 0, $e); + } catch (MissingConstructorArgumentsException $e) { + if (!$constructorParameter->getType()->allowsNull()) { + throw $e; + } + $parameterData = null; } // Don't run set for a parameter passed to the constructor diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 68f062cd5dcc..333f48779dc2 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -182,6 +182,23 @@ public function testConstructorWithObjectTypeHintDenormalize() $this->assertEquals('rab', $obj->getInner()->bar); } + public function testConstructorWithUnconstructableNullableObjectTypeHintDenormalize() + { + $data = array( + 'id' => 10, + 'inner' => null, + ); + + $normalizer = new ObjectNormalizer(); + $serializer = new Serializer(array($normalizer)); + $normalizer->setSerializer($serializer); + + $obj = $normalizer->denormalize($data, DummyWithNullableConstructorObject::class); + $this->assertInstanceOf(DummyWithNullableConstructorObject::class, $obj); + $this->assertEquals(10, $obj->getId()); + $this->assertNull($obj->getInner()); + } + /** * @expectedException \Symfony\Component\Serializer\Exception\RuntimeException * @expectedExceptionMessage Could not determine the class of the parameter "unknown". @@ -1109,3 +1126,25 @@ public function getFoo() return $this->Foo; } } + +class DummyWithNullableConstructorObject +{ + private $id; + private $inner; + + public function __construct($id, ?ObjectConstructorDummy $inner) + { + $this->id = $id; + $this->inner = $inner; + } + + public function getId() + { + return $this->id; + } + + public function getInner() + { + return $this->inner; + } +}