[Serializer] Add Support for in CustomNormalizer

This commit is contained in:
Christopher Davis 2017-02-22 10:41:23 -05:00 committed by Fabien Potencier
parent eb1183111a
commit ec9242d1ee
5 changed files with 107 additions and 9 deletions

View File

@ -27,6 +27,8 @@ use Symfony\Component\Serializer\SerializerAwareInterface;
*/
abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
use ObjectToPopulateTrait;
const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
const OBJECT_TO_POPULATE = 'object_to_populate';
const GROUPS = 'groups';
@ -317,12 +319,7 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
$format = null;
}
if (
isset($context[static::OBJECT_TO_POPULATE]) &&
is_object($context[static::OBJECT_TO_POPULATE]) &&
$context[static::OBJECT_TO_POPULATE] instanceof $class
) {
$object = $context[static::OBJECT_TO_POPULATE];
if (null !== $object = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) {
unset($context[static::OBJECT_TO_POPULATE]);
return $object;

View File

@ -19,10 +19,11 @@ use Symfony\Component\Serializer\SerializerAwareTrait;
*/
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
private $cache = array();
use ObjectToPopulateTrait;
use SerializerAwareTrait;
private $cache = array();
/**
* {@inheritdoc}
*/
@ -36,7 +37,7 @@ class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, Se
*/
public function denormalize($data, $class, $format = null, array $context = array())
{
$object = new $class();
$object = $this->extractObjectToPopulate($class, $context) ?: new $class();
$object->denormalize($this->serializer, $data, $format, $context);
return $object;

View File

@ -0,0 +1,41 @@
<?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\Normalizer;
trait ObjectToPopulateTrait
{
/**
* Extract the `object_to_populate` field from the context if it exists
* and is an instance of the provided $class.
*
* @param string $class The class the object should be
* @param $context The denormalization context
* @param string $key They in which to look for the object to populate.
* Keeps backwards compatibility with `AbstractNormalizer`.
*
* @return object|null an object if things check out, null otherwise
*/
protected function extractObjectToPopulate($class, array $context, $key = null)
{
$key = $key ?: 'object_to_populate';
if (
isset($context[$key]) &&
is_object($context[$key]) &&
$context[$key] instanceof $class
) {
return $context[$key];
}
return null;
}
}

View File

@ -56,6 +56,18 @@ class CustomNormalizerTest extends TestCase
$this->assertNull($obj->xmlFoo);
}
public function testDenormalizeWithObjectToPopulateUsesProvidedObject()
{
$expected = new ScalarDummy();
$obj = $this->normalizer->denormalize('foo', ScalarDummy::class, 'json', array(
'object_to_populate' => $expected,
));
$this->assertSame($expected, $obj);
$this->assertEquals('foo', $obj->foo);
$this->assertNull($obj->xmlFoo);
}
public function testSupportsNormalization()
{
$this->assertTrue($this->normalizer->supportsNormalization(new ScalarDummy()));

View File

@ -0,0 +1,47 @@
<?php
namespace Symfony\Component\Serializer\Tests\Normalizer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
use Symfony\Component\Serializer\Tests\Fixtures\ProxyDummy;
class ObjectToPopulateTraitTest extends TestCase
{
use ObjectToPopulateTrait;
public function testExtractObjectToPopulateReturnsNullWhenKeyIsMissing()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array());
$this->assertNull($object);
}
public function testExtractObjectToPopulateReturnsNullWhenNonObjectIsProvided()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => 'not an object',
));
$this->assertNull($object);
}
public function testExtractObjectToPopulateReturnsNullWhenTheClassIsNotAnInstanceOfTheProvidedClass()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => new \stdClass(),
));
$this->assertNull($object);
}
public function testExtractObjectToPopulateReturnsObjectWhenEverythingChecksOut()
{
$expected = new ProxyDummy();
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => $expected,
));
$this->assertSame($expected, $object);
}
}