diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 853e00eb2bbec..e3f7fb0a14610 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.1.0 +----- + +* added `MissingConstructorArgumentsException` new exception for deserialization failure + of objects that needs data insertion in constructor +* added an optional `default_constructor_arguments` option of context to specify a default data in + case the object is not initializable by its constructor because of data missing + 4.0.0 ----- diff --git a/src/Symfony/Component/Serializer/Exception/MissingConstructorArgumentsException.php b/src/Symfony/Component/Serializer/Exception/MissingConstructorArgumentsException.php new file mode 100644 index 0000000000000..b9b768b53f5e7 --- /dev/null +++ b/src/Symfony/Component/Serializer/Exception/MissingConstructorArgumentsException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * IncompleteInputDataException. + * + * @author Maxime VEBER + */ +class MissingConstructorArgumentsException extends RuntimeException +{ +} diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index c43f0598a820a..6442e98a1473f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\Exception\CircularReferenceException; +use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\RuntimeException; @@ -36,6 +37,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn const GROUPS = 'groups'; const ATTRIBUTES = 'attributes'; const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes'; + const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments'; /** * @var int @@ -308,6 +310,7 @@ protected function getConstructor(array &$data, $class, array &$context, \Reflec * @return object * * @throws RuntimeException + * @throws MissingConstructorArgumentsException */ protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null) { @@ -353,10 +356,12 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref // Don't run set for a parameter passed to the constructor $params[] = $parameterData; unset($data[$key]); + } elseif (isset($context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key])) { + $params[] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key]; } elseif ($constructorParameter->isDefaultValueAvailable()) { $params[] = $constructorParameter->getDefaultValue(); } else { - throw new RuntimeException( + throw new MissingConstructorArgumentsException( sprintf( 'Cannot create an instance of %s from serialized data because its constructor requires parameter "%s" to be present.', $class, diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index f2d389a0df07e..68f062cd5dcc6 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -203,6 +203,38 @@ public function testConstructorWithUnknownObjectTypeHintDenormalize() $normalizer->denormalize($data, DummyWithConstructorInexistingObject::class); } + /** + * @expectedException \Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException + * @expectedExceptionMessage Cannot create an instance of Symfony\Component\Serializer\Tests\Normalizer\DummyValueObject from serialized data because its constructor requires parameter "bar" to be present. + */ + public function testConstructorWithMissingData() + { + $data = array( + 'foo' => 10, + ); + + $normalizer = new ObjectNormalizer(); + + $normalizer->denormalize($data, DummyValueObject::class); + } + + public function testFillWithEmptyDataWhenMissingData() + { + $data = array( + 'foo' => 10, + ); + + $normalizer = new ObjectNormalizer(); + + $result = $normalizer->denormalize($data, DummyValueObject::class, 'json', array( + 'default_constructor_arguments' => array( + DummyValueObject::class => array('foo' => '', 'bar' => ''), + ), + )); + + $this->assertEquals(new DummyValueObject(10, ''), $result); + } + public function testGroupsNormalize() { $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); @@ -1025,6 +1057,17 @@ public function __construct($id, Unknown $unknown) { } } +class DummyValueObject +{ + private $foo; + private $bar; + + public function __construct($foo, $bar) + { + $this->foo = $foo; + $this->bar = $bar; + } +} class JsonNumber {