Skip to content

Commit 79a7fcf

Browse files
Nek-fabpot
authored andcommitted
[Serializer] context option for denormalization
1 parent af092fd commit 79a7fcf

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
CHANGELOG
22
=========
33

4+
4.1.0
5+
-----
6+
7+
* added `MissingConstructorArgumentsException` new exception for deserialization failure
8+
of objects that needs data insertion in constructor
9+
* added an optional `default_constructor_arguments` option of context to specify a default data in
10+
case the object is not initializable by its constructor because of data missing
11+
412
4.0.0
513
-----
614

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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\Exception;
13+
14+
/**
15+
* IncompleteInputDataException.
16+
*
17+
* @author Maxime VEBER <[email protected]>
18+
*/
19+
class MissingConstructorArgumentsException extends RuntimeException
20+
{
21+
}

Normalizer/AbstractNormalizer.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Serializer\Normalizer;
1313

1414
use Symfony\Component\Serializer\Exception\CircularReferenceException;
15+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
1516
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
1617
use Symfony\Component\Serializer\Exception\LogicException;
1718
use Symfony\Component\Serializer\Exception\RuntimeException;
@@ -36,6 +37,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
3637
const GROUPS = 'groups';
3738
const ATTRIBUTES = 'attributes';
3839
const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
40+
const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments';
3941

4042
/**
4143
* @var int
@@ -308,6 +310,7 @@ protected function getConstructor(array &$data, $class, array &$context, \Reflec
308310
* @return object
309311
*
310312
* @throws RuntimeException
313+
* @throws MissingConstructorArgumentsException
311314
*/
312315
protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null)
313316
{
@@ -353,10 +356,12 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref
353356
// Don't run set for a parameter passed to the constructor
354357
$params[] = $parameterData;
355358
unset($data[$key]);
359+
} elseif (isset($context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key])) {
360+
$params[] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
356361
} elseif ($constructorParameter->isDefaultValueAvailable()) {
357362
$params[] = $constructorParameter->getDefaultValue();
358363
} else {
359-
throw new RuntimeException(
364+
throw new MissingConstructorArgumentsException(
360365
sprintf(
361366
'Cannot create an instance of %s from serialized data because its constructor requires parameter "%s" to be present.',
362367
$class,

Tests/Normalizer/ObjectNormalizerTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,38 @@ public function testConstructorWithUnknownObjectTypeHintDenormalize()
203203
$normalizer->denormalize($data, DummyWithConstructorInexistingObject::class);
204204
}
205205

206+
/**
207+
* @expectedException \Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException
208+
* @expectedExceptionMessage Cannot create an instance of Symfony\Component\Serializer\Tests\Normalizer\DummyValueObject from serialized data because its constructor requires parameter "bar" to be present.
209+
*/
210+
public function testConstructorWithMissingData()
211+
{
212+
$data = array(
213+
'foo' => 10,
214+
);
215+
216+
$normalizer = new ObjectNormalizer();
217+
218+
$normalizer->denormalize($data, DummyValueObject::class);
219+
}
220+
221+
public function testFillWithEmptyDataWhenMissingData()
222+
{
223+
$data = array(
224+
'foo' => 10,
225+
);
226+
227+
$normalizer = new ObjectNormalizer();
228+
229+
$result = $normalizer->denormalize($data, DummyValueObject::class, 'json', array(
230+
'default_constructor_arguments' => array(
231+
DummyValueObject::class => array('foo' => '', 'bar' => ''),
232+
),
233+
));
234+
235+
$this->assertEquals(new DummyValueObject(10, ''), $result);
236+
}
237+
206238
public function testGroupsNormalize()
207239
{
208240
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
@@ -1025,6 +1057,17 @@ public function __construct($id, Unknown $unknown)
10251057
{
10261058
}
10271059
}
1060+
class DummyValueObject
1061+
{
1062+
private $foo;
1063+
private $bar;
1064+
1065+
public function __construct($foo, $bar)
1066+
{
1067+
$this->foo = $foo;
1068+
$this->bar = $bar;
1069+
}
1070+
}
10281071

10291072
class JsonNumber
10301073
{

0 commit comments

Comments
 (0)