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.
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.
However, ReflectionExtractor
is not a representation of PropertyInfoExtractorInterface
.
On the following line:
symfony/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php
Lines 177 to 178 in c168c2c
...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_lock
The 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