4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Serializer\Tests\Normalizer;
14 use Doctrine\Common\Annotations\AnnotationReader;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
17 use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
18 use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
19 use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
20 use Symfony\Component\Serializer\Serializer;
21 use Symfony\Component\Serializer\SerializerInterface;
22 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
23 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyChild;
24 use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
25 use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
26 use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
28 class PropertyNormalizerTest extends TestCase
31 * @var PropertyNormalizer
35 * @var SerializerInterface
39 protected function setUp()
41 $this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
42 $this->normalizer = new PropertyNormalizer();
43 $this->normalizer->setSerializer($this->serializer);
46 public function testNormalize()
48 $obj = new PropertyDummy();
51 $obj->setCamelCase('camelcase');
53 array('foo' => 'foo', 'bar' => 'bar', 'camelCase' => 'camelcase'),
54 $this->normalizer->normalize($obj, 'any')
58 public function testDenormalize()
60 $obj = $this->normalizer->denormalize(
61 array('foo' => 'foo', 'bar' => 'bar'),
62 __NAMESPACE__.'\PropertyDummy',
65 $this->assertEquals('foo', $obj->foo);
66 $this->assertEquals('bar', $obj->getBar());
69 public function testNormalizeWithParentClass()
71 $group = new GroupDummyChild();
72 $group->setBaz('baz');
73 $group->setFoo('foo');
74 $group->setBar('bar');
75 $group->setKevin('Kevin');
76 $group->setCoopTilleuls('coop');
78 array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', 'coopTilleuls' => 'coop', 'fooBar' => null, 'symfony' => null, 'baz' => 'baz'),
79 $this->normalizer->normalize($group, 'any')
83 public function testDenormalizeWithParentClass()
85 $obj = $this->normalizer->denormalize(
86 array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', 'baz' => 'baz'),
87 GroupDummyChild::class,
90 $this->assertEquals('foo', $obj->getFoo());
91 $this->assertEquals('bar', $obj->getBar());
92 $this->assertEquals('Kevin', $obj->getKevin());
93 $this->assertEquals('baz', $obj->getBaz());
94 $this->assertNull($obj->getSymfony());
97 public function testConstructorDenormalize()
99 $obj = $this->normalizer->denormalize(
100 array('foo' => 'foo', 'bar' => 'bar'),
101 __NAMESPACE__.'\PropertyConstructorDummy',
104 $this->assertEquals('foo', $obj->getFoo());
105 $this->assertEquals('bar', $obj->getBar());
108 public function testConstructorDenormalizeWithNullArgument()
110 $obj = $this->normalizer->denormalize(
111 array('foo' => null, 'bar' => 'bar'),
112 __NAMESPACE__.'\PropertyConstructorDummy', '
115 $this->assertNull($obj->getFoo());
116 $this->assertEquals('bar', $obj->getBar());
120 * @dataProvider provideCallbacks
122 public function testCallbacks($callbacks, $value, $result, $message)
124 $this->normalizer->setCallbacks($callbacks);
126 $obj = new PropertyConstructorDummy('', $value);
130 $this->normalizer->normalize($obj, 'any'),
136 * @expectedException \InvalidArgumentException
138 public function testUncallableCallbacks()
140 $this->normalizer->setCallbacks(array('bar' => null));
142 $obj = new PropertyConstructorDummy('baz', 'quux');
144 $this->normalizer->normalize($obj, 'any');
147 public function testIgnoredAttributes()
149 $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase'));
151 $obj = new PropertyDummy();
157 $this->normalizer->normalize($obj, 'any')
161 public function testGroupsNormalize()
163 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
164 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
165 $this->normalizer->setSerializer($this->serializer);
167 $obj = new GroupDummy();
170 $obj->setFooBar('fooBar');
171 $obj->setSymfony('symfony');
172 $obj->setKevin('kevin');
173 $obj->setCoopTilleuls('coopTilleuls');
175 $this->assertEquals(array(
177 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c'))));
179 // The PropertyNormalizer is also able to hydrate properties from parent classes
180 $this->assertEquals(array(
181 'symfony' => 'symfony',
183 'fooBar' => 'fooBar',
186 'coopTilleuls' => 'coopTilleuls',
187 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c'))));
190 public function testGroupsDenormalize()
192 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
193 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
194 $this->normalizer->setSerializer($this->serializer);
196 $obj = new GroupDummy();
199 $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
201 $normalized = $this->normalizer->denormalize(
203 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
205 array(PropertyNormalizer::GROUPS => array('a'))
207 $this->assertEquals($obj, $normalized);
211 $normalized = $this->normalizer->denormalize(
213 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
215 array(PropertyNormalizer::GROUPS => array('a', 'b'))
217 $this->assertEquals($obj, $normalized);
220 public function testGroupsNormalizeWithNameConverter()
222 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
223 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
224 $this->normalizer->setSerializer($this->serializer);
226 $obj = new GroupDummy();
227 $obj->setFooBar('@dunglas');
228 $obj->setSymfony('@coopTilleuls');
229 $obj->setCoopTilleuls('les-tilleuls.coop');
234 'foo_bar' => '@dunglas',
235 'symfony' => '@coopTilleuls',
237 $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('name_converter')))
241 public function testGroupsDenormalizeWithNameConverter()
243 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
244 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
245 $this->normalizer->setSerializer($this->serializer);
247 $obj = new GroupDummy();
248 $obj->setFooBar('@dunglas');
249 $obj->setSymfony('@coopTilleuls');
253 $this->normalizer->denormalize(array(
255 'foo_bar' => '@dunglas',
256 'symfony' => '@coopTilleuls',
257 'coop_tilleuls' => 'les-tilleuls.coop',
258 ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(PropertyNormalizer::GROUPS => array('name_converter')))
262 public function provideCallbacks()
267 'bar' => function ($bar) {
272 array('foo' => '', 'bar' => 'baz'),
277 'bar' => function ($bar) {
282 array('foo' => '', 'bar' => null),
287 'bar' => function ($bar) {
288 return $bar->format('d-m-Y H:i:s');
291 new \DateTime('2011-09-10 06:30:00'),
292 array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
297 'bar' => function ($bars) {
299 foreach ($bars as $bar) {
300 $foos .= $bar->getFoo();
306 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
307 array('foo' => '', 'bar' => 'bazquux'),
308 'Collect a property',
312 'bar' => function ($bars) {
313 return \count($bars);
316 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
317 array('foo' => '', 'bar' => 2),
324 * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
326 public function testUnableToNormalizeCircularReference()
328 $serializer = new Serializer(array($this->normalizer));
329 $this->normalizer->setSerializer($serializer);
330 $this->normalizer->setCircularReferenceLimit(2);
332 $obj = new PropertyCircularReferenceDummy();
334 $this->normalizer->normalize($obj);
337 public function testSiblingReference()
339 $serializer = new Serializer(array($this->normalizer));
340 $this->normalizer->setSerializer($serializer);
342 $siblingHolder = new PropertySiblingHolder();
345 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
346 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
347 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
349 $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
352 public function testCircularReferenceHandler()
354 $serializer = new Serializer(array($this->normalizer));
355 $this->normalizer->setSerializer($serializer);
356 $this->normalizer->setCircularReferenceHandler(function ($obj) {
357 return \get_class($obj);
360 $obj = new PropertyCircularReferenceDummy();
362 $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy');
363 $this->assertEquals($expected, $this->normalizer->normalize($obj));
366 public function testDenormalizeNonExistingAttribute()
370 $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
374 public function testDenormalizeShouldIgnoreStaticProperty()
376 $obj = $this->normalizer->denormalize(array('outOfScope' => true), __NAMESPACE__.'\PropertyDummy');
378 $this->assertEquals(new PropertyDummy(), $obj);
379 $this->assertEquals('out_of_scope', PropertyDummy::$outOfScope);
383 * @expectedException \Symfony\Component\Serializer\Exception\LogicException
384 * @expectedExceptionMessage Cannot normalize attribute "bar" because the injected serializer is not a normalizer
386 public function testUnableToNormalizeObjectAttribute()
388 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
389 $this->normalizer->setSerializer($serializer);
391 $obj = new PropertyDummy();
392 $object = new \stdClass();
393 $obj->setBar($object);
395 $this->normalizer->normalize($obj, 'any');
398 public function testNoTraversableSupport()
400 $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
403 public function testNoStaticPropertySupport()
405 $this->assertFalse($this->normalizer->supportsNormalization(new StaticPropertyDummy()));
408 public function testMaxDepth()
410 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
411 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
412 $serializer = new Serializer(array($this->normalizer));
413 $this->normalizer->setSerializer($serializer);
415 $level1 = new MaxDepthDummy();
416 $level1->foo = 'level1';
418 $level2 = new MaxDepthDummy();
419 $level2->foo = 'level2';
420 $level1->child = $level2;
422 $level3 = new MaxDepthDummy();
423 $level3->foo = 'level3';
424 $level2->child = $level3;
426 $result = $serializer->normalize($level1, null, array(PropertyNormalizer::ENABLE_MAX_DEPTH => true));
441 $this->assertEquals($expected, $result);
444 public function testInheritedPropertiesSupport()
446 $this->assertTrue($this->normalizer->supportsNormalization(new PropertyChildDummy()));
452 public static $outOfScope = 'out_of_scope';
455 protected $camelCase;
457 public function getBar()
462 public function setBar($bar)
467 public function getCamelCase()
469 return $this->camelCase;
472 public function setCamelCase($camelCase)
474 $this->camelCase = $camelCase;
478 class PropertyConstructorDummy
483 public function __construct($foo, $bar)
489 public function getFoo()
494 public function getBar()
500 class PropertyCamelizedDummy
502 private $kevinDunglas;
506 public function __construct($kevinDunglas = null)
508 $this->kevinDunglas = $kevinDunglas;
512 class StaticPropertyDummy
514 private static $property = 'value';
517 class PropertyParentDummy
519 private $foo = 'bar';
522 class PropertyChildDummy extends PropertyParentDummy