-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
Symfony version(s) affected
5.4.39, 6.4.7, 7.0.7
Description
In the following commit, a change was introduced to the ObjectNormalizer constructor signature.
900d034
Now, ObjectNormalizer requires PropertyInfoExtractorInterface to be passed as last argument (or a null value).
This is aliased in framework to match property_info service.
| ->alias(PropertyInfoExtractorInterface::class, 'property_info') |
So, under normal circumstances in an application that uses Symfony framework, this is filled with PropertyInfoExtractorInterface (when autowiring, for example).
If null value is passed, ReflectionExtractor object is created in it's stead.
| $this->propertyInfoExtractor = $propertyInfoExtractor ?: new ReflectionExtractor(); |
However, ReflectionExtractor is not a representation of PropertyInfoExtractorInterface.
| class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface, PropertyInitializableExtractorInterface, PropertyReadInfoExtractorInterface, PropertyWriteInfoExtractorInterface, ConstructorArgumentTypeExtractorInterface |
On the following line:
symfony/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php
Lines 177 to 178 in c168c2c
| return $this->propertyInfoExtractor->isWritable($class, $attribute) | |
| || ($writeInfo = $this->propertyInfoExtractor->getWriteInfo($class, $attribute)) && PropertyWriteInfo::TYPE_NONE !== $writeInfo->getType(); |
...the property that can contain either
PropertyInfoExtractorInterface or ReflectionExtractor is used - a method getWriteInfo() is called that exists only on ReflectionExtractor. This means that PropertyInfoExtractorInterface cannot be used and will cause a PHP error, which results in inability to denormalize that object.
Ergo, in case of our app, we cannot use the property_info service (nor it's caching), and must fall back to null.
How to reproduce
We have this error...
Caused by
Error: Call to undefined method Symfony\Component\PropertyInfo\PropertyInfoExtractor::getWriteInfo()
...happen when ObjectNormalizer is asked to denormalize an object of the following type:
$objectState = $this->denormalizer->denormalize($data, ObjectState::class, $format, $context);final class ObjectState
{
/** @var string */
public $identifier;
/** @var string */
public $groupIdentifier;
private function __construct(string $identifier, string $groupIdentifier)
{
$this->identifier = $identifier;
$this->groupIdentifier = $groupIdentifier;
}
}with data (partial extract):
action: assign_object_state
identifier: locked
groupIdentifier: ez_lockThe ObjectNormalizer service is defined as follows:
foo.serializer.object_normalizer:
class: Symfony\Component\Serializer\Normalizer\ObjectNormalizer
arguments:
$propertyTypeExtractor: '@property_info'
$propertyInfoExtractor: '@property_info'
tags:
- serializer.normalizer # a different tag is used in our own code since we have a dedicated serializer, but you get the idea.Possible Solution
ObjectNormalizer, in lieu of adding PropertyInfoExtractorInterface to ReflectionExtractor, should perform checks against method presence to better inform developers about what is actually going on and/or a fallback should exist in cases where we are not dealing with ReflectionExtractor instance.
Additional Context
No response