Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6fb0978

Browse files
committed
Add a normalizer that support JsonSerializable objects
Handles circular references
1 parent 83b53f4 commit 6fb0978

File tree

5 files changed

+197
-0
lines changed

5 files changed

+197
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
<tag name="serializer.normalizer" priority="-1000" />
2727
</service>
2828

29+
<!-- Json Normalizer -->
30+
<service id="serializer.normalizer.json" class="Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer" public="false">
31+
<!-- Run after all custom normalizers, but before the ObjectNormalizer -->
32+
<tag name="serializer.normalizer" priority="-900" />
33+
</service>
34+
2935
<!-- Loader -->
3036
<service id="serializer.mapping.chain_loader" class="Symfony\Component\Serializer\Mapping\Loader\LoaderChain" public="false">
3137
<argument type="collection" />

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.0.1
5+
-----
6+
7+
* added support for serializing objects that implement `JsonSerializable`
8+
49
2.7.0
510
-----
611

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Normalizer;
13+
14+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
15+
use Symfony\Component\Serializer\Exception\LogicException;
16+
17+
/**
18+
* A normalizer that uses an objects own JsonSerializable implementation.
19+
*
20+
* @author Fred Cox <[email protected]>
21+
*/
22+
class JsonSerializableNormalizer extends AbstractNormalizer
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function normalize($object, $format = null, array $context = array())
28+
{
29+
if ($this->isCircularReference($object, $context)) {
30+
return $this->handleCircularReference($object);
31+
}
32+
33+
if (!$object instanceof \JsonSerializable) {
34+
throw new InvalidArgumentException(sprintf('The object must implement "%s".', \JsonSerializable::class));
35+
}
36+
37+
if (!$this->serializer instanceof NormalizerInterface) {
38+
throw new LogicException('Cannot normalize object because injected serializer is not a normalizer');
39+
}
40+
41+
return $this->serializer->normalize($object->jsonSerialize(), $format, $context);
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
public function supportsNormalization($data, $format = null)
48+
{
49+
return $data instanceof \JsonSerializable;
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function supportsDenormalization($data, $type, $format = null)
56+
{
57+
return false;
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public function denormalize($data, $class, $format = null, array $context = array())
64+
{
65+
throw new LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class));
66+
}
67+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
class JsonSerializableDummy implements \JsonSerializable
15+
{
16+
public function jsonSerialize()
17+
{
18+
return array(
19+
'foo' => 'a',
20+
'bar' => 'b',
21+
'baz' => 'c',
22+
'qux' => $this,
23+
);
24+
}
25+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Normalizer;
13+
14+
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
15+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
16+
use Symfony\Component\Serializer\SerializerInterface;
17+
use Symfony\Component\Serializer\Tests\Fixtures\JsonSerializableDummy;
18+
19+
/**
20+
* @author Fred Cox <[email protected]>
21+
*/
22+
class JsonSerializableNormalizerTest extends \PHPUnit_Framework_TestCase
23+
{
24+
/**
25+
* @var JsonSerializableNormalizer
26+
*/
27+
private $normalizer;
28+
29+
/**
30+
* @var \PHPUnit_Framework_MockObject_MockObject|SerializerInterface
31+
*/
32+
private $serializer;
33+
34+
protected function setUp()
35+
{
36+
$this->serializer = $this->getMock(JsonSerializerNormalizer::class);
37+
$this->normalizer = new JsonSerializableNormalizer();
38+
$this->normalizer->setSerializer($this->serializer);
39+
}
40+
41+
public function testSupportNormalization()
42+
{
43+
$this->assertTrue($this->normalizer->supportsNormalization(new JsonSerializableDummy()));
44+
$this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
45+
}
46+
47+
public function testNormalize()
48+
{
49+
$this->serializer
50+
->expects($this->once())
51+
->method('normalize')
52+
->will($this->returnCallback(function($data) {
53+
$this->assertArraySubset(array('foo' => 'a', 'bar' => 'b', 'baz' => 'c'), $data);
54+
55+
return 'string_object';
56+
}))
57+
;
58+
59+
$this->assertEquals('string_object', $this->normalizer->normalize(new JsonSerializableDummy()));
60+
}
61+
62+
/**
63+
* @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
64+
*/
65+
public function testCircularNormalize()
66+
{
67+
$this->normalizer->setCircularReferenceLimit(1);
68+
69+
$this->serializer
70+
->expects($this->once())
71+
->method('normalize')
72+
->will($this->returnCallback(function($data, $format, $context) {
73+
$this->normalizer->normalize($data['qux'], $format, $context);
74+
75+
return 'string_object';
76+
}))
77+
;
78+
79+
$this->assertEquals('string_object', $this->normalizer->normalize(new JsonSerializableDummy()));
80+
}
81+
82+
/**
83+
* @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException
84+
* @expectedExceptionMessage The object must implement "JsonSerializable".
85+
*/
86+
public function testInvalidDataThrowException()
87+
{
88+
$this->normalizer->normalize(new \stdClass());
89+
}
90+
}
91+
92+
abstract class JsonSerializerNormalizer implements SerializerInterface, NormalizerInterface
93+
{
94+
}

0 commit comments

Comments
 (0)