[Serializer] Introduce ObjectNormalizer
This commit is contained in:
parent
ff70902dcb
commit
0050bbb345
@ -15,6 +15,8 @@ CHANGELOG
|
|||||||
`PropertyNormalizer::setCamelizedAttributes()` are replaced by
|
`PropertyNormalizer::setCamelizedAttributes()` are replaced by
|
||||||
`CamelCaseToSnakeCaseNameConverter`
|
`CamelCaseToSnakeCaseNameConverter`
|
||||||
* [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface`
|
* [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface`
|
||||||
|
* added `ObjectNormalizer` leveraging the `PropertyAccess` component to normalize
|
||||||
|
objects containing both properties and getters / setters / issers / hassers methods.
|
||||||
|
|
||||||
2.6.0
|
2.6.0
|
||||||
-----
|
-----
|
||||||
|
162
src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php
Normal file
162
src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
|
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||||
|
use Symfony\Component\Serializer\Exception\LogicException;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||||
|
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts between objects and arrays using the PropertyAccess component.
|
||||||
|
*
|
||||||
|
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||||
|
*/
|
||||||
|
class ObjectNormalizer extends AbstractNormalizer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PropertyAccessorInterface
|
||||||
|
*/
|
||||||
|
protected $propertyAccessor;
|
||||||
|
|
||||||
|
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null)
|
||||||
|
{
|
||||||
|
parent::__construct($classMetadataFactory, $nameConverter);
|
||||||
|
|
||||||
|
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function supportsNormalization($data, $format = null)
|
||||||
|
{
|
||||||
|
return is_object($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @throws CircularReferenceException
|
||||||
|
*/
|
||||||
|
public function normalize($object, $format = null, array $context = array())
|
||||||
|
{
|
||||||
|
if ($this->isCircularReference($object, $context)) {
|
||||||
|
return $this->handleCircularReference($object);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
$attributes = $this->getAllowedAttributes($object, $context, true);
|
||||||
|
|
||||||
|
// If not using groups, detect manually
|
||||||
|
if (false === $attributes) {
|
||||||
|
$attributes = array();
|
||||||
|
|
||||||
|
// methods
|
||||||
|
$reflClass = new \ReflectionClass($object);
|
||||||
|
foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
|
||||||
|
if (
|
||||||
|
!$reflMethod->isConstructor() &&
|
||||||
|
!$reflMethod->isDestructor() &&
|
||||||
|
0 === $reflMethod->getNumberOfRequiredParameters()
|
||||||
|
) {
|
||||||
|
$name = $reflMethod->getName();
|
||||||
|
|
||||||
|
if (strpos($name, 'get') === 0 || strpos($name, 'has') === 0) {
|
||||||
|
// getters and hassers
|
||||||
|
$attributes[lcfirst(substr($name, 3))] = true;
|
||||||
|
} elseif (strpos($name, 'is') === 0) {
|
||||||
|
// issers
|
||||||
|
$attributes[lcfirst(substr($name, 2))] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// properties
|
||||||
|
foreach ($reflClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflProperty) {
|
||||||
|
$attributes[$reflProperty->getName()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes = array_keys($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($attributes as $attribute) {
|
||||||
|
if (in_array($attribute, $this->ignoredAttributes)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributeValue = $this->propertyAccessor->getValue($object, $attribute);
|
||||||
|
|
||||||
|
if (isset($this->callbacks[$attribute])) {
|
||||||
|
$attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $attributeValue && !is_scalar($attributeValue)) {
|
||||||
|
if (!$this->serializer instanceof NormalizerInterface) {
|
||||||
|
throw new LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributeValue = $this->serializer->normalize($attributeValue, $format, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->nameConverter) {
|
||||||
|
$attribute = $this->nameConverter->normalize($attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data[$attribute] = $attributeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function supportsDenormalization($data, $type, $format = null)
|
||||||
|
{
|
||||||
|
return class_exists($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function denormalize($data, $class, $format = null, array $context = array())
|
||||||
|
{
|
||||||
|
$allowedAttributes = $this->getAllowedAttributes($class, $context, true);
|
||||||
|
$normalizedData = $this->prepareForDenormalization($data);
|
||||||
|
|
||||||
|
$reflectionClass = new \ReflectionClass($class);
|
||||||
|
$object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes);
|
||||||
|
|
||||||
|
foreach ($normalizedData as $attribute => $value) {
|
||||||
|
$allowed = $allowedAttributes === false || in_array($attribute, $allowedAttributes);
|
||||||
|
$ignored = in_array($attribute, $this->ignoredAttributes);
|
||||||
|
|
||||||
|
if ($allowed && !$ignored) {
|
||||||
|
if ($this->nameConverter) {
|
||||||
|
$attribute = $this->nameConverter->normalize($attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->propertyAccessor->setValue($object, $attribute, $value);
|
||||||
|
} catch (NoSuchPropertyException $exception) {
|
||||||
|
// Properties not found are ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,497 @@
|
|||||||
|
<?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\Normalizer;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Serializer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||||
|
*/
|
||||||
|
class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ObjectNormalizerTest
|
||||||
|
*/
|
||||||
|
private $normalizer;
|
||||||
|
/**
|
||||||
|
* @var SerializerInterface
|
||||||
|
*/
|
||||||
|
private $serializer;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->serializer = $this->getMock(__NAMESPACE__.'\ObjectSerializerNormalizer');
|
||||||
|
$this->normalizer = new ObjectNormalizer();
|
||||||
|
$this->normalizer->setSerializer($this->serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNormalize()
|
||||||
|
{
|
||||||
|
$obj = new ObjectDummy();
|
||||||
|
$object = new \stdClass();
|
||||||
|
$obj->setFoo('foo');
|
||||||
|
$obj->bar = 'bar';
|
||||||
|
$obj->setBaz(true);
|
||||||
|
$obj->setCamelCase('camelcase');
|
||||||
|
$obj->setObject($object);
|
||||||
|
|
||||||
|
$this->serializer
|
||||||
|
->expects($this->once())
|
||||||
|
->method('normalize')
|
||||||
|
->with($object, 'any')
|
||||||
|
->will($this->returnValue('string_object'))
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'foo' => 'foo',
|
||||||
|
'bar' => 'bar',
|
||||||
|
'baz' => true,
|
||||||
|
'fooBar' => 'foobar',
|
||||||
|
'camelCase' => 'camelcase',
|
||||||
|
'object' => 'string_object',
|
||||||
|
),
|
||||||
|
$this->normalizer->normalize($obj, 'any')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalize()
|
||||||
|
{
|
||||||
|
$obj = $this->normalizer->denormalize(
|
||||||
|
array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
|
||||||
|
__NAMESPACE__.'\ObjectDummy',
|
||||||
|
'any'
|
||||||
|
);
|
||||||
|
$this->assertEquals('foo', $obj->getFoo());
|
||||||
|
$this->assertEquals('bar', $obj->bar);
|
||||||
|
$this->assertTrue($obj->isBaz());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeWithObject()
|
||||||
|
{
|
||||||
|
$data = new \stdClass();
|
||||||
|
$data->foo = 'foo';
|
||||||
|
$data->bar = 'bar';
|
||||||
|
$data->fooBar = 'foobar';
|
||||||
|
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectDummy', 'any');
|
||||||
|
$this->assertEquals('foo', $obj->getFoo());
|
||||||
|
$this->assertEquals('bar', $obj->bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLegacyDenormalizeOnCamelCaseFormat()
|
||||||
|
{
|
||||||
|
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
$this->normalizer->setCamelizedAttributes(array('camel_case'));
|
||||||
|
$obj = $this->normalizer->denormalize(
|
||||||
|
array('camel_case' => 'camelCase'),
|
||||||
|
__NAMESPACE__.'\ObjectDummy'
|
||||||
|
);
|
||||||
|
$this->assertEquals('camelCase', $obj->getCamelCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeNull()
|
||||||
|
{
|
||||||
|
$this->assertEquals(new ObjectDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\ObjectDummy'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConstructorDenormalize()
|
||||||
|
{
|
||||||
|
$obj = $this->normalizer->denormalize(
|
||||||
|
array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
|
||||||
|
__NAMESPACE__.'\ObjectConstructorDummy', 'any');
|
||||||
|
$this->assertEquals('foo', $obj->getFoo());
|
||||||
|
$this->assertEquals('bar', $obj->bar);
|
||||||
|
$this->assertTrue($obj->isBaz());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConstructorDenormalizeWithMissingOptionalArgument()
|
||||||
|
{
|
||||||
|
$obj = $this->normalizer->denormalize(
|
||||||
|
array('foo' => 'test', 'baz' => array(1, 2, 3)),
|
||||||
|
__NAMESPACE__.'\ObjectConstructorOptionalArgsDummy', 'any');
|
||||||
|
$this->assertEquals('test', $obj->getFoo());
|
||||||
|
$this->assertEquals(array(), $obj->bar);
|
||||||
|
$this->assertEquals(array(1, 2, 3), $obj->getBaz());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConstructorWithObjectDenormalize()
|
||||||
|
{
|
||||||
|
$data = new \stdClass();
|
||||||
|
$data->foo = 'foo';
|
||||||
|
$data->bar = 'bar';
|
||||||
|
$data->baz = true;
|
||||||
|
$data->fooBar = 'foobar';
|
||||||
|
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectConstructorDummy', 'any');
|
||||||
|
$this->assertEquals('foo', $obj->getFoo());
|
||||||
|
$this->assertEquals('bar', $obj->bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGroupsNormalize()
|
||||||
|
{
|
||||||
|
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
|
||||||
|
$this->normalizer = new ObjectNormalizer($classMetadataFactory);
|
||||||
|
$this->normalizer->setSerializer($this->serializer);
|
||||||
|
|
||||||
|
$obj = new GroupDummy();
|
||||||
|
$obj->setFoo('foo');
|
||||||
|
$obj->setBar('bar');
|
||||||
|
$obj->setFooBar('fooBar');
|
||||||
|
$obj->setSymfony('symfony');
|
||||||
|
$obj->setKevin('kevin');
|
||||||
|
$obj->setCoopTilleuls('coopTilleuls');
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'bar' => 'bar',
|
||||||
|
), $this->normalizer->normalize($obj, null, array('groups' => array('c'))));
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'symfony' => 'symfony',
|
||||||
|
'foo' => 'foo',
|
||||||
|
'fooBar' => 'fooBar',
|
||||||
|
'bar' => 'bar',
|
||||||
|
'kevin' => 'kevin',
|
||||||
|
'coopTilleuls' => 'coopTilleuls',
|
||||||
|
), $this->normalizer->normalize($obj, null, array('groups' => array('a', 'c'))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGroupsDenormalize()
|
||||||
|
{
|
||||||
|
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
|
||||||
|
$this->normalizer = new ObjectNormalizer($classMetadataFactory);
|
||||||
|
$this->normalizer->setSerializer($this->serializer);
|
||||||
|
|
||||||
|
$obj = new GroupDummy();
|
||||||
|
$obj->setFoo('foo');
|
||||||
|
|
||||||
|
$toNormalize = array('foo' => 'foo', 'bar' => 'bar');
|
||||||
|
|
||||||
|
$normalized = $this->normalizer->denormalize(
|
||||||
|
$toNormalize,
|
||||||
|
'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
|
||||||
|
null,
|
||||||
|
array('groups' => array('a'))
|
||||||
|
);
|
||||||
|
$this->assertEquals($obj, $normalized);
|
||||||
|
|
||||||
|
$obj->setBar('bar');
|
||||||
|
|
||||||
|
$normalized = $this->normalizer->denormalize(
|
||||||
|
$toNormalize,
|
||||||
|
'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
|
||||||
|
null,
|
||||||
|
array('groups' => array('a', 'b'))
|
||||||
|
);
|
||||||
|
$this->assertEquals($obj, $normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideCallbacks
|
||||||
|
*/
|
||||||
|
public function testCallbacks($callbacks, $value, $result, $message)
|
||||||
|
{
|
||||||
|
$this->normalizer->setCallbacks($callbacks);
|
||||||
|
|
||||||
|
$obj = new ObjectConstructorDummy('', $value, true);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
$result,
|
||||||
|
$this->normalizer->normalize($obj, 'any'),
|
||||||
|
$message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testUncallableCallbacks()
|
||||||
|
{
|
||||||
|
$this->normalizer->setCallbacks(array('bar' => null));
|
||||||
|
|
||||||
|
$obj = new ObjectConstructorDummy('baz', 'quux', true);
|
||||||
|
|
||||||
|
$this->normalizer->normalize($obj, 'any');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIgnoredAttributes()
|
||||||
|
{
|
||||||
|
$this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'baz', 'camelCase', 'object'));
|
||||||
|
|
||||||
|
$obj = new ObjectDummy();
|
||||||
|
$obj->setFoo('foo');
|
||||||
|
$obj->bar = 'bar';
|
||||||
|
$obj->setBaz(true);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array('fooBar' => 'foobar'),
|
||||||
|
$this->normalizer->normalize($obj, 'any')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideCallbacks()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'bar' => function ($bar) {
|
||||||
|
return 'baz';
|
||||||
|
},
|
||||||
|
),
|
||||||
|
'baz',
|
||||||
|
array('foo' => '', 'bar' => 'baz', 'baz' => true),
|
||||||
|
'Change a string',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'bar' => function ($bar) {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
'baz',
|
||||||
|
array('foo' => '', 'bar' => null, 'baz' => true),
|
||||||
|
'Null an item',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'bar' => function ($bar) {
|
||||||
|
return $bar->format('d-m-Y H:i:s');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
new \DateTime('2011-09-10 06:30:00'),
|
||||||
|
array('foo' => '', 'bar' => '10-09-2011 06:30:00', 'baz' => true),
|
||||||
|
'Format a date',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'bar' => function ($bars) {
|
||||||
|
$foos = '';
|
||||||
|
foreach ($bars as $bar) {
|
||||||
|
$foos .= $bar->getFoo();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $foos;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
|
||||||
|
array('foo' => '', 'bar' => 'bazquux', 'baz' => true),
|
||||||
|
'Collect a property',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'bar' => function ($bars) {
|
||||||
|
return count($bars);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
|
||||||
|
array('foo' => '', 'bar' => 2, 'baz' => true),
|
||||||
|
'Count a property',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Serializer\Exception\LogicException
|
||||||
|
* @expectedExceptionMessage Cannot normalize attribute "object" because injected serializer is not a normalizer
|
||||||
|
*/
|
||||||
|
public function testUnableToNormalizeObjectAttribute()
|
||||||
|
{
|
||||||
|
$serializer = $this->getMock('Symfony\Component\Serializer\SerializerInterface');
|
||||||
|
$this->normalizer->setSerializer($serializer);
|
||||||
|
|
||||||
|
$obj = new ObjectDummy();
|
||||||
|
$object = new \stdClass();
|
||||||
|
$obj->setObject($object);
|
||||||
|
|
||||||
|
$this->normalizer->normalize($obj, 'any');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
|
||||||
|
*/
|
||||||
|
public function testUnableToNormalizeCircularReference()
|
||||||
|
{
|
||||||
|
$serializer = new Serializer(array($this->normalizer));
|
||||||
|
$this->normalizer->setSerializer($serializer);
|
||||||
|
$this->normalizer->setCircularReferenceLimit(2);
|
||||||
|
|
||||||
|
$obj = new CircularReferenceDummy();
|
||||||
|
|
||||||
|
$this->normalizer->normalize($obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSiblingReference()
|
||||||
|
{
|
||||||
|
$serializer = new Serializer(array($this->normalizer));
|
||||||
|
$this->normalizer->setSerializer($serializer);
|
||||||
|
|
||||||
|
$siblingHolder = new SiblingHolder();
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
|
||||||
|
'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
|
||||||
|
'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
|
||||||
|
);
|
||||||
|
$this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCircularReferenceHandler()
|
||||||
|
{
|
||||||
|
$serializer = new Serializer(array($this->normalizer));
|
||||||
|
$this->normalizer->setSerializer($serializer);
|
||||||
|
$this->normalizer->setCircularReferenceHandler(function ($obj) {
|
||||||
|
return get_class($obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
$obj = new CircularReferenceDummy();
|
||||||
|
|
||||||
|
$expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy');
|
||||||
|
$this->assertEquals($expected, $this->normalizer->normalize($obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeNonExistingAttribute()
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
new ObjectDummy(),
|
||||||
|
$this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\ObjectDummy')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectDummy
|
||||||
|
{
|
||||||
|
protected $foo;
|
||||||
|
public $bar;
|
||||||
|
private $baz;
|
||||||
|
protected $camelCase;
|
||||||
|
protected $object;
|
||||||
|
|
||||||
|
public function getFoo()
|
||||||
|
{
|
||||||
|
return $this->foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFoo($foo)
|
||||||
|
{
|
||||||
|
$this->foo = $foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isBaz()
|
||||||
|
{
|
||||||
|
return $this->baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBaz($baz)
|
||||||
|
{
|
||||||
|
$this->baz = $baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFooBar()
|
||||||
|
{
|
||||||
|
return $this->foo.$this->bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCamelCase()
|
||||||
|
{
|
||||||
|
return $this->camelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCamelCase($camelCase)
|
||||||
|
{
|
||||||
|
$this->camelCase = $camelCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function otherMethod()
|
||||||
|
{
|
||||||
|
throw new \RuntimeException("Dummy::otherMethod() should not be called");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setObject($object)
|
||||||
|
{
|
||||||
|
$this->object = $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObject()
|
||||||
|
{
|
||||||
|
return $this->object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectConstructorDummy
|
||||||
|
{
|
||||||
|
protected $foo;
|
||||||
|
public $bar;
|
||||||
|
private $baz;
|
||||||
|
|
||||||
|
public function __construct($foo, $bar, $baz)
|
||||||
|
{
|
||||||
|
$this->foo = $foo;
|
||||||
|
$this->bar = $bar;
|
||||||
|
$this->baz = $baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFoo()
|
||||||
|
{
|
||||||
|
return $this->foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isBaz()
|
||||||
|
{
|
||||||
|
return $this->baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function otherMethod()
|
||||||
|
{
|
||||||
|
throw new \RuntimeException("Dummy::otherMethod() should not be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ObjectSerializerNormalizer implements SerializerInterface, NormalizerInterface
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectConstructorOptionalArgsDummy
|
||||||
|
{
|
||||||
|
protected $foo;
|
||||||
|
public $bar;
|
||||||
|
private $baz;
|
||||||
|
|
||||||
|
public function __construct($foo, $bar = array(), $baz = array())
|
||||||
|
{
|
||||||
|
$this->foo = $foo;
|
||||||
|
$this->bar = $bar;
|
||||||
|
$this->baz = $baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFoo()
|
||||||
|
{
|
||||||
|
return $this->foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBaz()
|
||||||
|
{
|
||||||
|
return $this->baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function otherMethod()
|
||||||
|
{
|
||||||
|
throw new \RuntimeException("Dummy::otherMethod() should not be called");
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@
|
|||||||
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
||||||
"symfony/yaml": "~2.0|~3.0.0",
|
"symfony/yaml": "~2.0|~3.0.0",
|
||||||
"symfony/config": "~2.2|~3.0.0",
|
"symfony/config": "~2.2|~3.0.0",
|
||||||
|
"symfony/property-access": "~2.3|~3.0.0",
|
||||||
"doctrine/annotations": "~1.0",
|
"doctrine/annotations": "~1.0",
|
||||||
"doctrine/cache": "~1.0"
|
"doctrine/cache": "~1.0"
|
||||||
},
|
},
|
||||||
@ -29,7 +30,8 @@
|
|||||||
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
|
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
|
||||||
"doctrine/cache": "For using the default cached annotation reader and metadata cache.",
|
"doctrine/cache": "For using the default cached annotation reader and metadata cache.",
|
||||||
"symfony/yaml": "For using the default YAML mapping loader.",
|
"symfony/yaml": "For using the default YAML mapping loader.",
|
||||||
"symfony/config": "For using the XML mapping loader."
|
"symfony/config": "For using the XML mapping loader.",
|
||||||
|
"symfony/property-access": "For using the ObjectNormalizer."
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": { "Symfony\\Component\\Serializer\\": "" }
|
"psr-0": { "Symfony\\Component\\Serializer\\": "" }
|
||||||
|
Reference in New Issue
Block a user