[Serializer] Add Support of recursive denormalization on object_to_populate
This commit is contained in:
parent
fad7c8c01f
commit
5b723865b1
@ -6,6 +6,7 @@ CHANGELOG
|
||||
|
||||
* added the list of constraint violations' parameters in `ConstraintViolationListNormalizer`
|
||||
* added support for serializing `DateTimeZone` objects
|
||||
* added a `deep_object_to_populate` context option to recursive denormalize on `object_to_populate` object.
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
@ -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;
|
||||
@ -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 = [];
|
||||
@ -274,6 +276,13 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
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);
|
||||
|
@ -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];
|
||||
|
@ -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|null
|
||||
*/
|
||||
private $child;
|
||||
|
||||
public function setChild(?DeepObjectPopulateChildDummy $child)
|
||||
{
|
||||
$this->child = $child;
|
||||
}
|
||||
|
||||
public function getChild(): ?DeepObjectPopulateChildDummy
|
||||
{
|
||||
return $this->child;
|
||||
}
|
||||
}
|
@ -23,6 +23,8 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
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
|
||||
{
|
||||
@ -171,6 +173,48 @@ class AbstractObjectNormalizerTest extends TestCase
|
||||
$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,
|
||||
];
|
||||
|
||||
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
|
||||
$normalizer = new ObjectNormalizer($classMetadataFactory, null, null, new PhpDocExtractor());
|
||||
|
||||
$newChild = new DeepObjectPopulateChildDummy();
|
||||
$newChild->bar = 'bar-new';
|
||||
$newChild->foo = 'foo-old';
|
||||
|
||||
$serializer = $this->getMockBuilder(__NAMESPACE__.'\ObjectSerializerDenormalizer')->getMock();
|
||||
$serializer
|
||||
->method('supportsDenormalization')
|
||||
->with($this->arrayHasKey('bar'),
|
||||
$this->equalTo(DeepObjectPopulateChildDummy::class),
|
||||
$this->isNull(),
|
||||
$this->contains($child))
|
||||
->willReturn(true);
|
||||
$serializer->method('denormalize')->willReturn($newChild);
|
||||
|
||||
$normalizer->setSerializer($serializer);
|
||||
$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
|
||||
@ -348,3 +392,7 @@ class ArrayDenormalizerDummy implements DenormalizerInterface, SerializerAwareIn
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ObjectSerializerDenormalizer implements SerializerInterface, DenormalizerInterface
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user