Skip to content

Commit

Permalink
feature #28669 [Serializer] Object class resolver (alanpoulain)
Browse files Browse the repository at this point in the history
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 5a0cad2
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/Symfony/Component/Serializer/CHANGELOG.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ CHANGELOG
either `NormalizerInterface` or `DenormalizerInterface` either `NormalizerInterface` or `DenormalizerInterface`
* deprecated creating a `Serializer` with encoders which do not implement * deprecated creating a `Serializer` with encoders which do not implement
either `EncoderInterface` or `DecoderInterface` either `EncoderInterface` or `DecoderInterface`
* added the optional `$objectClassResolver` argument in `AbstractObjectNormalizer`
and `ObjectNormalizer` constructor


4.1.0 4.1.0
----- -----
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
* @var callable|null * @var callable|null
*/ */
private $maxDepthHandler; private $maxDepthHandler;
private $objectClassResolver;


/** /**
* @var ClassDiscriminatorResolverInterface|null * @var ClassDiscriminatorResolverInterface|null
*/ */
protected $classDiscriminatorResolver; 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); parent::__construct($classMetadataFactory, $nameConverter);


Expand All @@ -61,6 +62,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory
$classDiscriminatorResolver = new ClassDiscriminatorFromClassMetadata($classMetadataFactory); $classDiscriminatorResolver = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
} }
$this->classDiscriminatorResolver = $classDiscriminatorResolver; $this->classDiscriminatorResolver = $classDiscriminatorResolver;
$this->objectClassResolver = $objectClassResolver;
} }


/** /**
Expand All @@ -87,7 +89,7 @@ public function normalize($object, $format = null, array $context = array())
$data = array(); $data = array();
$stack = array(); $stack = array();
$attributes = $this->getAttributes($object, $format, $context); $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; $attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null;


foreach ($attributes as $attribute) { foreach ($attributes as $attribute) {
Expand Down Expand Up @@ -156,7 +158,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref
*/ */
protected function getAttributes($object, $format = null, array $context) 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']; $key = $class.'-'.$context['cache_key'];


if (isset($this->attributesCache[$key])) { if (isset($this->attributesCache[$key])) {
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ class ObjectNormalizer extends AbstractObjectNormalizer
{ {
protected $propertyAccessor; 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)) { if (!\class_exists(PropertyAccess::class)) {
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.'); 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(); $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
} }
Expand Down

0 comments on commit 5a0cad2

Please sign in to comment.