Permalink
Browse files

feature #28669 [Serializer] Object class resolver (alanpoulain)

This PR was squashed before being merged into the 4.2-dev branch (closes #28669).

Discussion
----------

[Serializer] Object class resolver

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

When normalizing an object, it could be useful to use a custom method to resolve the class name of it instead of using `get_class`.
For instance, Doctrine is using proxy classes for lazy-loading and we usually want the real class and not the proxied one.
That's why we are using this trait in API Platform: https://github.com/api-platform/core/blob/master/src/Util/ClassInfoTrait.php
With this feature, we could solve an issue in API Platform with the JSON-LD normalizer when the eager fetching is disabled.

Commits
-------

18d2143 [Serializer] Object class resolver
  • Loading branch information...
dunglas committed Oct 3, 2018
2 parents 0f653d8 + 18d2143 commit 5a0cad27ca82e54e2ed721f7910d436067fc2635
@@ -20,6 +20,8 @@ CHANGELOG
either `NormalizerInterface` or `DenormalizerInterface`
* deprecated creating a `Serializer` with encoders which do not implement
either `EncoderInterface` or `DecoderInterface`
* added the optional `$objectClassResolver` argument in `AbstractObjectNormalizer`
and `ObjectNormalizer` constructor
4.1.0
-----
@@ -45,13 +45,14 @@
* @var callable|null
*/
private $maxDepthHandler;
private $objectClassResolver;
/**
* @var ClassDiscriminatorResolverInterface|null
*/
protected $classDiscriminatorResolver;
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null)
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null)
{
parent::__construct($classMetadataFactory, $nameConverter);
@@ -61,6 +62,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory
$classDiscriminatorResolver = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
}
$this->classDiscriminatorResolver = $classDiscriminatorResolver;
$this->objectClassResolver = $objectClassResolver;
}
/**
@@ -87,7 +89,7 @@ public function normalize($object, $format = null, array $context = array())
$data = array();
$stack = array();
$attributes = $this->getAttributes($object, $format, $context);
$class = \get_class($object);
$class = $this->objectClassResolver ? \call_user_func($this->objectClassResolver, $object) : \get_class($object);
$attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null;
foreach ($attributes as $attribute) {
@@ -156,7 +158,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref
*/
protected function getAttributes($object, $format = null, array $context)
{
$class = \get_class($object);
$class = $this->objectClassResolver ? \call_user_func($this->objectClassResolver, $object) : \get_class($object);
$key = $class.'-'.$context['cache_key'];
if (isset($this->attributesCache[$key])) {
@@ -30,13 +30,13 @@ class ObjectNormalizer extends AbstractObjectNormalizer
{
protected $propertyAccessor;
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null)
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null)
{
if (!\class_exists(PropertyAccess::class)) {
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.');
}
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver);
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver);
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
}

0 comments on commit 5a0cad2

Please sign in to comment.