ObjectNormalizerTest.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Serializer\Tests\Normalizer;
  11. use Doctrine\Common\Annotations\AnnotationReader;
  12. use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
  13. use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
  14. use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
  15. use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
  16. use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
  17. use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
  18. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  19. use Symfony\Component\Serializer\Serializer;
  20. use Symfony\Component\Serializer\SerializerInterface;
  21. use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
  22. use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
  23. use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
  24. use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
  25. use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
  26. use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
  27. use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
  28. /**
  29. * @author Kévin Dunglas <dunglas@gmail.com>
  30. */
  31. class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
  32. {
  33. /**
  34. * @var ObjectNormalizer
  35. */
  36. private $normalizer;
  37. /**
  38. * @var SerializerInterface
  39. */
  40. private $serializer;
  41. protected function setUp()
  42. {
  43. $this->serializer = $this->getMockBuilder(__NAMESPACE__.'\ObjectSerializerNormalizer')->getMock();
  44. $this->normalizer = new ObjectNormalizer();
  45. $this->normalizer->setSerializer($this->serializer);
  46. }
  47. public function testNormalize()
  48. {
  49. $obj = new ObjectDummy();
  50. $object = new \stdClass();
  51. $obj->setFoo('foo');
  52. $obj->bar = 'bar';
  53. $obj->setBaz(true);
  54. $obj->setCamelCase('camelcase');
  55. $obj->setObject($object);
  56. $this->serializer
  57. ->expects($this->once())
  58. ->method('normalize')
  59. ->with($object, 'any')
  60. ->will($this->returnValue('string_object'))
  61. ;
  62. $this->assertEquals(
  63. array(
  64. 'foo' => 'foo',
  65. 'bar' => 'bar',
  66. 'baz' => true,
  67. 'fooBar' => 'foobar',
  68. 'camelCase' => 'camelcase',
  69. 'object' => 'string_object',
  70. ),
  71. $this->normalizer->normalize($obj, 'any')
  72. );
  73. }
  74. public function testDenormalize()
  75. {
  76. $obj = $this->normalizer->denormalize(
  77. array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
  78. __NAMESPACE__.'\ObjectDummy',
  79. 'any'
  80. );
  81. $this->assertEquals('foo', $obj->getFoo());
  82. $this->assertEquals('bar', $obj->bar);
  83. $this->assertTrue($obj->isBaz());
  84. }
  85. public function testDenormalizeWithObject()
  86. {
  87. $data = new \stdClass();
  88. $data->foo = 'foo';
  89. $data->bar = 'bar';
  90. $data->fooBar = 'foobar';
  91. $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectDummy', 'any');
  92. $this->assertEquals('foo', $obj->getFoo());
  93. $this->assertEquals('bar', $obj->bar);
  94. }
  95. public function testDenormalizeNull()
  96. {
  97. $this->assertEquals(new ObjectDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\ObjectDummy'));
  98. }
  99. public function testConstructorDenormalize()
  100. {
  101. $obj = $this->normalizer->denormalize(
  102. array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
  103. __NAMESPACE__.'\ObjectConstructorDummy', 'any');
  104. $this->assertEquals('foo', $obj->getFoo());
  105. $this->assertEquals('bar', $obj->bar);
  106. $this->assertTrue($obj->isBaz());
  107. }
  108. public function testConstructorDenormalizeWithNullArgument()
  109. {
  110. $obj = $this->normalizer->denormalize(
  111. array('foo' => 'foo', 'bar' => null, 'baz' => true),
  112. __NAMESPACE__.'\ObjectConstructorDummy', 'any');
  113. $this->assertEquals('foo', $obj->getFoo());
  114. $this->assertNull($obj->bar);
  115. $this->assertTrue($obj->isBaz());
  116. }
  117. public function testConstructorDenormalizeWithMissingOptionalArgument()
  118. {
  119. $obj = $this->normalizer->denormalize(
  120. array('foo' => 'test', 'baz' => array(1, 2, 3)),
  121. __NAMESPACE__.'\ObjectConstructorOptionalArgsDummy', 'any');
  122. $this->assertEquals('test', $obj->getFoo());
  123. $this->assertEquals(array(), $obj->bar);
  124. $this->assertEquals(array(1, 2, 3), $obj->getBaz());
  125. }
  126. public function testConstructorDenormalizeWithOptionalDefaultArgument()
  127. {
  128. $obj = $this->normalizer->denormalize(
  129. array('bar' => 'test'),
  130. __NAMESPACE__.'\ObjectConstructorArgsWithDefaultValueDummy', 'any');
  131. $this->assertEquals(array(), $obj->getFoo());
  132. $this->assertEquals('test', $obj->getBar());
  133. }
  134. public function testConstructorWithObjectDenormalize()
  135. {
  136. $data = new \stdClass();
  137. $data->foo = 'foo';
  138. $data->bar = 'bar';
  139. $data->baz = true;
  140. $data->fooBar = 'foobar';
  141. $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectConstructorDummy', 'any');
  142. $this->assertEquals('foo', $obj->getFoo());
  143. $this->assertEquals('bar', $obj->bar);
  144. }
  145. public function testGroupsNormalize()
  146. {
  147. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  148. $this->normalizer = new ObjectNormalizer($classMetadataFactory);
  149. $this->normalizer->setSerializer($this->serializer);
  150. $obj = new GroupDummy();
  151. $obj->setFoo('foo');
  152. $obj->setBar('bar');
  153. $obj->setFooBar('fooBar');
  154. $obj->setSymfony('symfony');
  155. $obj->setKevin('kevin');
  156. $obj->setCoopTilleuls('coopTilleuls');
  157. $this->assertEquals(array(
  158. 'bar' => 'bar',
  159. ), $this->normalizer->normalize($obj, null, array(ObjectNormalizer::GROUPS => array('c'))));
  160. $this->assertEquals(array(
  161. 'symfony' => 'symfony',
  162. 'foo' => 'foo',
  163. 'fooBar' => 'fooBar',
  164. 'bar' => 'bar',
  165. 'kevin' => 'kevin',
  166. 'coopTilleuls' => 'coopTilleuls',
  167. ), $this->normalizer->normalize($obj, null, array(ObjectNormalizer::GROUPS => array('a', 'c'))));
  168. }
  169. public function testGroupsDenormalize()
  170. {
  171. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  172. $this->normalizer = new ObjectNormalizer($classMetadataFactory);
  173. $this->normalizer->setSerializer($this->serializer);
  174. $obj = new GroupDummy();
  175. $obj->setFoo('foo');
  176. $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
  177. $normalized = $this->normalizer->denormalize(
  178. $toNormalize,
  179. 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
  180. null,
  181. array(ObjectNormalizer::GROUPS => array('a'))
  182. );
  183. $this->assertEquals($obj, $normalized);
  184. $obj->setBar('bar');
  185. $normalized = $this->normalizer->denormalize(
  186. $toNormalize,
  187. 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
  188. null,
  189. array(ObjectNormalizer::GROUPS => array('a', 'b'))
  190. );
  191. $this->assertEquals($obj, $normalized);
  192. }
  193. public function testNormalizeNoPropertyInGroup()
  194. {
  195. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  196. $this->normalizer = new ObjectNormalizer($classMetadataFactory);
  197. $this->normalizer->setSerializer($this->serializer);
  198. $obj = new GroupDummy();
  199. $obj->setFoo('foo');
  200. $this->assertEquals(array(), $this->normalizer->normalize($obj, null, array('groups' => array('notExist'))));
  201. }
  202. public function testGroupsNormalizeWithNameConverter()
  203. {
  204. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  205. $this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
  206. $this->normalizer->setSerializer($this->serializer);
  207. $obj = new GroupDummy();
  208. $obj->setFooBar('@dunglas');
  209. $obj->setSymfony('@coopTilleuls');
  210. $obj->setCoopTilleuls('les-tilleuls.coop');
  211. $this->assertEquals(
  212. array(
  213. 'bar' => null,
  214. 'foo_bar' => '@dunglas',
  215. 'symfony' => '@coopTilleuls',
  216. ),
  217. $this->normalizer->normalize($obj, null, array(ObjectNormalizer::GROUPS => array('name_converter')))
  218. );
  219. }
  220. public function testGroupsDenormalizeWithNameConverter()
  221. {
  222. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  223. $this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
  224. $this->normalizer->setSerializer($this->serializer);
  225. $obj = new GroupDummy();
  226. $obj->setFooBar('@dunglas');
  227. $obj->setSymfony('@coopTilleuls');
  228. $this->assertEquals(
  229. $obj,
  230. $this->normalizer->denormalize(array(
  231. 'bar' => null,
  232. 'foo_bar' => '@dunglas',
  233. 'symfony' => '@coopTilleuls',
  234. 'coop_tilleuls' => 'les-tilleuls.coop',
  235. ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(ObjectNormalizer::GROUPS => array('name_converter')))
  236. );
  237. }
  238. /**
  239. * @dataProvider provideCallbacks
  240. */
  241. public function testCallbacks($callbacks, $value, $result, $message)
  242. {
  243. $this->normalizer->setCallbacks($callbacks);
  244. $obj = new ObjectConstructorDummy('', $value, true);
  245. $this->assertEquals(
  246. $result,
  247. $this->normalizer->normalize($obj, 'any'),
  248. $message
  249. );
  250. }
  251. /**
  252. * @expectedException \InvalidArgumentException
  253. */
  254. public function testUncallableCallbacks()
  255. {
  256. $this->normalizer->setCallbacks(array('bar' => null));
  257. $obj = new ObjectConstructorDummy('baz', 'quux', true);
  258. $this->normalizer->normalize($obj, 'any');
  259. }
  260. public function testIgnoredAttributes()
  261. {
  262. $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'baz', 'camelCase', 'object'));
  263. $obj = new ObjectDummy();
  264. $obj->setFoo('foo');
  265. $obj->bar = 'bar';
  266. $obj->setBaz(true);
  267. $this->assertEquals(
  268. array('fooBar' => 'foobar'),
  269. $this->normalizer->normalize($obj, 'any')
  270. );
  271. }
  272. public function testIgnoredAttributesDenormalize()
  273. {
  274. $this->normalizer->setIgnoredAttributes(array('fooBar', 'bar', 'baz'));
  275. $obj = new ObjectDummy();
  276. $obj->setFoo('foo');
  277. $this->assertEquals(
  278. $obj,
  279. $this->normalizer->denormalize(array('fooBar' => 'fooBar', 'foo' => 'foo', 'baz' => 'baz'), __NAMESPACE__.'\ObjectDummy')
  280. );
  281. }
  282. public function provideCallbacks()
  283. {
  284. return array(
  285. array(
  286. array(
  287. 'bar' => function ($bar) {
  288. return 'baz';
  289. },
  290. ),
  291. 'baz',
  292. array('foo' => '', 'bar' => 'baz', 'baz' => true),
  293. 'Change a string',
  294. ),
  295. array(
  296. array(
  297. 'bar' => function ($bar) {
  298. return;
  299. },
  300. ),
  301. 'baz',
  302. array('foo' => '', 'bar' => null, 'baz' => true),
  303. 'Null an item',
  304. ),
  305. array(
  306. array(
  307. 'bar' => function ($bar) {
  308. return $bar->format('d-m-Y H:i:s');
  309. },
  310. ),
  311. new \DateTime('2011-09-10 06:30:00'),
  312. array('foo' => '', 'bar' => '10-09-2011 06:30:00', 'baz' => true),
  313. 'Format a date',
  314. ),
  315. array(
  316. array(
  317. 'bar' => function ($bars) {
  318. $foos = '';
  319. foreach ($bars as $bar) {
  320. $foos .= $bar->getFoo();
  321. }
  322. return $foos;
  323. },
  324. ),
  325. array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
  326. array('foo' => '', 'bar' => 'bazquux', 'baz' => true),
  327. 'Collect a property',
  328. ),
  329. array(
  330. array(
  331. 'bar' => function ($bars) {
  332. return count($bars);
  333. },
  334. ),
  335. array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
  336. array('foo' => '', 'bar' => 2, 'baz' => true),
  337. 'Count a property',
  338. ),
  339. );
  340. }
  341. /**
  342. * @expectedException \Symfony\Component\Serializer\Exception\LogicException
  343. * @expectedExceptionMessage Cannot normalize attribute "object" because the injected serializer is not a normalizer
  344. */
  345. public function testUnableToNormalizeObjectAttribute()
  346. {
  347. $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
  348. $this->normalizer->setSerializer($serializer);
  349. $obj = new ObjectDummy();
  350. $object = new \stdClass();
  351. $obj->setObject($object);
  352. $this->normalizer->normalize($obj, 'any');
  353. }
  354. /**
  355. * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
  356. */
  357. public function testUnableToNormalizeCircularReference()
  358. {
  359. $serializer = new Serializer(array($this->normalizer));
  360. $this->normalizer->setSerializer($serializer);
  361. $this->normalizer->setCircularReferenceLimit(2);
  362. $obj = new CircularReferenceDummy();
  363. $this->normalizer->normalize($obj);
  364. }
  365. public function testSiblingReference()
  366. {
  367. $serializer = new Serializer(array($this->normalizer));
  368. $this->normalizer->setSerializer($serializer);
  369. $siblingHolder = new SiblingHolder();
  370. $expected = array(
  371. 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
  372. 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
  373. 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
  374. );
  375. $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
  376. }
  377. public function testCircularReferenceHandler()
  378. {
  379. $serializer = new Serializer(array($this->normalizer));
  380. $this->normalizer->setSerializer($serializer);
  381. $this->normalizer->setCircularReferenceHandler(function ($obj) {
  382. return get_class($obj);
  383. });
  384. $obj = new CircularReferenceDummy();
  385. $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy');
  386. $this->assertEquals($expected, $this->normalizer->normalize($obj));
  387. }
  388. public function testDenormalizeNonExistingAttribute()
  389. {
  390. $this->assertEquals(
  391. new ObjectDummy(),
  392. $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\ObjectDummy')
  393. );
  394. }
  395. public function testNoTraversableSupport()
  396. {
  397. $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
  398. }
  399. public function testNormalizeStatic()
  400. {
  401. $this->assertEquals(array('foo' => 'K'), $this->normalizer->normalize(new ObjectWithStaticPropertiesAndMethods()));
  402. }
  403. public function testNormalizeNotSerializableContext()
  404. {
  405. $objectDummy = new ObjectDummy();
  406. $expected = array(
  407. 'foo' => null,
  408. 'baz' => null,
  409. 'fooBar' => '',
  410. 'camelCase' => null,
  411. 'object' => null,
  412. 'bar' => null,
  413. );
  414. $this->assertEquals($expected, $this->normalizer->normalize($objectDummy, null, array('not_serializable' => function () {
  415. })));
  416. }
  417. public function testMaxDepth()
  418. {
  419. $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  420. $this->normalizer = new ObjectNormalizer($classMetadataFactory);
  421. $serializer = new Serializer(array($this->normalizer));
  422. $this->normalizer->setSerializer($serializer);
  423. $level1 = new MaxDepthDummy();
  424. $level1->foo = 'level1';
  425. $level2 = new MaxDepthDummy();
  426. $level2->foo = 'level2';
  427. $level1->child = $level2;
  428. $level3 = new MaxDepthDummy();
  429. $level3->foo = 'level3';
  430. $level2->child = $level3;
  431. $result = $serializer->normalize($level1, null, array(ObjectNormalizer::ENABLE_MAX_DEPTH => true));
  432. $expected = array(
  433. 'bar' => null,
  434. 'foo' => 'level1',
  435. 'child' => array(
  436. 'bar' => null,
  437. 'foo' => 'level2',
  438. 'child' => array(
  439. 'bar' => null,
  440. 'child' => null,
  441. ),
  442. ),
  443. );
  444. $this->assertEquals($expected, $result);
  445. }
  446. /**
  447. * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
  448. */
  449. public function testThrowUnexpectedValueException()
  450. {
  451. $this->normalizer->denormalize(array('foo' => 'bar'), ObjectTypeHinted::class);
  452. }
  453. public function testDenomalizeRecursive()
  454. {
  455. $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
  456. $normalizer = new ObjectNormalizer(null, null, null, $extractor);
  457. $serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
  458. $obj = $serializer->denormalize(array(
  459. 'inner' => array('foo' => 'foo', 'bar' => 'bar'),
  460. 'date' => '1988/01/21',
  461. 'inners' => array(array('foo' => 1), array('foo' => 2)),
  462. ), ObjectOuter::class);
  463. $this->assertSame('foo', $obj->getInner()->foo);
  464. $this->assertSame('bar', $obj->getInner()->bar);
  465. $this->assertSame('1988-01-21', $obj->getDate()->format('Y-m-d'));
  466. $this->assertSame(1, $obj->getInners()[0]->foo);
  467. $this->assertSame(2, $obj->getInners()[1]->foo);
  468. }
  469. public function testAcceptJsonNumber()
  470. {
  471. $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
  472. $normalizer = new ObjectNormalizer(null, null, null, $extractor);
  473. $serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
  474. $this->assertSame(10.0, $serializer->denormalize(array('number' => 10), JsonNumber::class, 'json')->number);
  475. $this->assertSame(10.0, $serializer->denormalize(array('number' => 10), JsonNumber::class, 'jsonld')->number);
  476. }
  477. /**
  478. * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
  479. * @expectedExceptionMessage The type of the "date" attribute for class "Symfony\Component\Serializer\Tests\Normalizer\ObjectOuter" must be one of "DateTimeInterface" ("string" given).
  480. */
  481. public function testRejectInvalidType()
  482. {
  483. $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
  484. $serializer = new Serializer(array($normalizer));
  485. $serializer->denormalize(array('date' => 'foo'), ObjectOuter::class);
  486. }
  487. /**
  488. * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
  489. * @expectedExceptionMessage The type of the key "a" must be "int" ("string" given).
  490. */
  491. public function testRejectInvalidKey()
  492. {
  493. $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
  494. $normalizer = new ObjectNormalizer(null, null, null, $extractor);
  495. $serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
  496. $serializer->denormalize(array('inners' => array('a' => array('foo' => 1))), ObjectOuter::class);
  497. }
  498. public function testExtractAttributesRespectsFormat()
  499. {
  500. $normalizer = new FormatAndContextAwareNormalizer();
  501. $data = new ObjectDummy();
  502. $data->setFoo('bar');
  503. $data->bar = 'foo';
  504. $this->assertSame(array('foo' => 'bar', 'bar' => 'foo'), $normalizer->normalize($data, 'foo_and_bar_included'));
  505. }
  506. public function testExtractAttributesRespectsContext()
  507. {
  508. $normalizer = new FormatAndContextAwareNormalizer();
  509. $data = new ObjectDummy();
  510. $data->setFoo('bar');
  511. $data->bar = 'foo';
  512. $this->assertSame(array('foo' => 'bar', 'bar' => 'foo'), $normalizer->normalize($data, null, array('include_foo_and_bar' => true)));
  513. }
  514. }
  515. class ObjectDummy
  516. {
  517. protected $foo;
  518. public $bar;
  519. private $baz;
  520. protected $camelCase;
  521. protected $object;
  522. public function getFoo()
  523. {
  524. return $this->foo;
  525. }
  526. public function setFoo($foo)
  527. {
  528. $this->foo = $foo;
  529. }
  530. public function isBaz()
  531. {
  532. return $this->baz;
  533. }
  534. public function setBaz($baz)
  535. {
  536. $this->baz = $baz;
  537. }
  538. public function getFooBar()
  539. {
  540. return $this->foo.$this->bar;
  541. }
  542. public function getCamelCase()
  543. {
  544. return $this->camelCase;
  545. }
  546. public function setCamelCase($camelCase)
  547. {
  548. $this->camelCase = $camelCase;
  549. }
  550. public function otherMethod()
  551. {
  552. throw new \RuntimeException('Dummy::otherMethod() should not be called');
  553. }
  554. public function setObject($object)
  555. {
  556. $this->object = $object;
  557. }
  558. public function getObject()
  559. {
  560. return $this->object;
  561. }
  562. }
  563. class ObjectConstructorDummy
  564. {
  565. protected $foo;
  566. public $bar;
  567. private $baz;
  568. public function __construct($foo, $bar, $baz)
  569. {
  570. $this->foo = $foo;
  571. $this->bar = $bar;
  572. $this->baz = $baz;
  573. }
  574. public function getFoo()
  575. {
  576. return $this->foo;
  577. }
  578. public function isBaz()
  579. {
  580. return $this->baz;
  581. }
  582. public function otherMethod()
  583. {
  584. throw new \RuntimeException('Dummy::otherMethod() should not be called');
  585. }
  586. }
  587. abstract class ObjectSerializerNormalizer implements SerializerInterface, NormalizerInterface
  588. {
  589. }
  590. class ObjectConstructorOptionalArgsDummy
  591. {
  592. protected $foo;
  593. public $bar;
  594. private $baz;
  595. public function __construct($foo, $bar = array(), $baz = array())
  596. {
  597. $this->foo = $foo;
  598. $this->bar = $bar;
  599. $this->baz = $baz;
  600. }
  601. public function getFoo()
  602. {
  603. return $this->foo;
  604. }
  605. public function getBaz()
  606. {
  607. return $this->baz;
  608. }
  609. public function otherMethod()
  610. {
  611. throw new \RuntimeException('Dummy::otherMethod() should not be called');
  612. }
  613. }
  614. class ObjectConstructorArgsWithDefaultValueDummy
  615. {
  616. protected $foo;
  617. protected $bar;
  618. public function __construct($foo = array(), $bar)
  619. {
  620. $this->foo = $foo;
  621. $this->bar = $bar;
  622. }
  623. public function getFoo()
  624. {
  625. return $this->foo;
  626. }
  627. public function getBar()
  628. {
  629. return $this->bar;
  630. }
  631. public function otherMethod()
  632. {
  633. throw new \RuntimeException('Dummy::otherMethod() should not be called');
  634. }
  635. }
  636. class ObjectWithStaticPropertiesAndMethods
  637. {
  638. public $foo = 'K';
  639. public static $bar = 'A';
  640. public static function getBaz()
  641. {
  642. return 'L';
  643. }
  644. }
  645. class ObjectTypeHinted
  646. {
  647. public function setFoo(array $f)
  648. {
  649. }
  650. }
  651. class ObjectOuter
  652. {
  653. private $inner;
  654. private $date;
  655. /**
  656. * @var ObjectInner[]
  657. */
  658. private $inners;
  659. public function getInner()
  660. {
  661. return $this->inner;
  662. }
  663. public function setInner(ObjectInner $inner)
  664. {
  665. $this->inner = $inner;
  666. }
  667. public function setDate(\DateTimeInterface $date)
  668. {
  669. $this->date = $date;
  670. }
  671. public function getDate()
  672. {
  673. return $this->date;
  674. }
  675. public function setInners(array $inners)
  676. {
  677. $this->inners = $inners;
  678. }
  679. public function getInners()
  680. {
  681. return $this->inners;
  682. }
  683. }
  684. class ObjectInner
  685. {
  686. public $foo;
  687. public $bar;
  688. }
  689. class FormatAndContextAwareNormalizer extends ObjectNormalizer
  690. {
  691. protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = array())
  692. {
  693. if (in_array($attribute, array('foo', 'bar')) && 'foo_and_bar_included' === $format) {
  694. return true;
  695. }
  696. if (in_array($attribute, array('foo', 'bar')) && isset($context['include_foo_and_bar']) && true === $context['include_foo_and_bar']) {
  697. return true;
  698. }
  699. return false;
  700. }
  701. }
  702. class JsonNumber
  703. {
  704. /**
  705. * @var float
  706. */
  707. public $number;
  708. }