Skip to content

Commit

Permalink
Add deep populate option #21669
Browse files Browse the repository at this point in the history
  • Loading branch information
jewome62 committed Mar 19, 2019
1 parent 2ff8c19 commit e8f290f
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Symfony/Component/Serializer/CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@ CHANGELOG
-----

* added the list of constraint violations' parameters in `ConstraintViolationListNormalizer`
* added a `deep_object_to_populate` context option to recursive denormalize on `object_to_populate` object.

4.2.0
-----
Expand Down
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
Expand All @@ -38,6 +39,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
const SKIP_NULL_VALUES = 'skip_null_values';
const MAX_DEPTH_HANDLER = 'max_depth_handler';
const EXCLUDE_FROM_CACHE_KEY = 'exclude_from_cache_key';
const DEEP_OBJECT_TO_POPULATE = 'deep_object_to_populate';

private $propertyTypeExtractor;
private $typesCache = [];
Expand Down Expand Up @@ -274,6 +276,13 @@ public function denormalize($data, $class, $format = null, array $context = [])
continue;
}

if ($context[self::DEEP_OBJECT_TO_POPULATE] ?? $this->defaultContext[self::DEEP_OBJECT_TO_POPULATE] ?? false) {
try {
$context[self::OBJECT_TO_POPULATE] = $this->getAttributeValue($object, $attribute, $format, $context);
} catch (NoSuchPropertyException $e) {
}
}

$value = $this->validateAndDenormalize($class, $attribute, $value, $format, $context);
try {
$this->setAttributeValue($object, $attribute, $value, $format, $context);
Expand Down
Expand Up @@ -26,7 +26,7 @@ trait ObjectToPopulateTrait
*/
protected function extractObjectToPopulate($class, array $context, $key = null)
{
$key = $key ?: 'object_to_populate';
$key = $key ?: AbstractNormalizer::OBJECT_TO_POPULATE;

if (isset($context[$key]) && \is_object($context[$key]) && $context[$key] instanceof $class) {
return $context[$key];
Expand Down
@@ -0,0 +1,22 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Tests\Fixtures;

/**
* @author Jérôme Desjardin <jewome62@gmail.com>
*/
class DeepObjectPopulateChildDummy
{
public $foo;

public $bar;
}
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Tests\Fixtures;

/**
* @author Jérôme Desjardin <jewome62@gmail.com>
*/
class DeepObjectPopulateParentDummy
{
/**
* @var DeepObjectPopulateChildDummy
*/
private $child;

public function setChild(DeepObjectPopulateChildDummy $child)
{
$this->child = $child;
}

public function getChild()
{
return $this->child;
}
}
Expand Up @@ -23,6 +23,8 @@
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateChildDummy;
use Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateParentDummy;

class AbstractObjectNormalizerTest extends TestCase
{
Expand Down Expand Up @@ -171,6 +173,28 @@ public function testSkipNullValues()
$result = $normalizer->normalize($dummy, null, [AbstractObjectNormalizer::SKIP_NULL_VALUES => true]);
$this->assertSame(['bar' => 'present'], $result);
}

public function testDeepObjectToPopulate()
{
$child = new DeepObjectPopulateChildDummy();
$child->bar = 'bar-old';
$child->foo = 'foo-old';

$parent = new DeepObjectPopulateParentDummy();

$parent->setChild($child);

$context = [
AbstractObjectNormalizer::OBJECT_TO_POPULATE => $parent,
AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true
];

$normalizer = new ObjectNormalizer();
$normalizer->denormalize(['child' => [ 'bar' => 'bar-new']], 'Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateParentDummy', null, $context);

$this->assertSame('bar-new', $parent->getChild()->bar);
$this->assertSame('foo-old', $parent->getChild()->foo);
}
}

class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer
Expand Down

0 comments on commit e8f290f

Please sign in to comment.