feature #13500 [Serializer] Normalizers can serialize collections and scalars (dunglas)

This PR was squashed before being merged into the 2.7 branch (closes #13500).

Discussion
----------

[Serializer] Normalizers can serialize collections and scalars

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT
| Doc PR       | n/a

Currently, the logic for serializing `array` and scalars is hardcoded in the serializer. This is not possible to have a custom serializer normalizing collections. This a big limitation, for instance it's not possible to create an normalizer creating [Hydra collections](http://www.hydra-cg.com/spec/latest/core/#h-collections) for a PHP array.

This PR fix that.

Commits
-------

1cf8eb2 [Serializer] Normalizers can serialize collections and scalars
This commit is contained in:
Fabien Potencier 2015-02-11 11:46:00 +01:00
commit 7af0196d89
2 changed files with 24 additions and 5 deletions

View File

@ -33,6 +33,7 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
{
@ -118,6 +119,11 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/
public function normalize($data, $format = null, array $context = array())
{
// If a normalizer supports the given data, use it
if ($normalizer = $this->getNormalizer($data, $format)) {
return $normalizer->normalize($data, $format, $context);
}
if (null === $data || is_scalar($data)) {
return $data;
}
@ -172,21 +178,25 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
/**
* Returns a matching normalizer.
*
* @param object $data The object to get the serializer for
* @param mixed $data Data to get the serializer for
* @param string $format format name, present to give the option to normalizers to act differently based on formats
*
* @return NormalizerInterface|null
*/
private function getNormalizer($data, $format)
{
$class = get_class($data);
if (isset($this->normalizerCache[$class][$format])) {
return $this->normalizerCache[$class][$format];
if ($isObject = is_object($data)) {
$class = get_class($data);
if (isset($this->normalizerCache[$class][$format])) {
return $this->normalizerCache[$class][$format];
}
}
foreach ($this->normalizers as $normalizer) {
if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format)) {
$this->normalizerCache[$class][$format] = $normalizer;
if ($isObject) {
$this->normalizerCache[$class][$format] = $normalizer;
}
return $normalizer;
}

View File

@ -73,6 +73,15 @@ class SerializerTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($this->serializer->denormalize(json_encode($data), 'stdClass', 'json'));
}
public function testCustomNormalizerCanNormalizeCollectionsAndScalar()
{
$this->serializer = new Serializer(array(new TestNormalizer()), array());
$this->assertNull($this->serializer->normalize(array('a', 'b')));
$this->assertNull($this->serializer->normalize(new \ArrayObject(array('c', 'd'))));
$this->assertNull($this->serializer->normalize(array()));
$this->assertNull($this->serializer->normalize('test'));
}
public function testSerialize()
{
$this->serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new JsonEncoder()));