Description
Symfony version(s) affected
6.0.6
Description
Deserializing Union types fails on first subtype deserialization fail.
My usecase:
I would like to create a field in a json object where the client can set null
, false
or a valid date time value, in order to differentiate between 3 states: deleted, unchanged, updated (to the datetime value).
How to reproduce
symfony/serializer
needed.
class Test
{
public null|bool|\DateTime $changed = false;
}
class ServiceWithAutoWiring {
public function __construct(SerializerInterface $serializer)
{
$format = [DateTimeNormalizer::FORMAT_KEY => \DateTimeInterface::ISO8601];
$a = $serializer->deserialize('{ "changed": null }', Test::class, 'json', $format); // OK
$b = $serializer->deserialize('{ "changed": "2022-03-22T16:15:05+0000" }', Test::class, 'json', $format); // OK
$c = $serializer->deserialize('{ "changed": false }', Test::class, 'json', $format); // Fails with exception
}
}
Possible Solution
I think the proper solution would be to try to deserialize all the possible types from the union type, and if all fail, only then trait it as the deserialization failed.
Additional Context
I tried to reverse the order of the array returning from \Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor::extractFromReflectionType
and it seems to solve the problem. (Which is a workaround, and not a proper fix)
This makes the boolean
type checked before the DateTime
and returns before the validation can fail on the parsing of date time.
That is why I think checking all possible outcomes before aborting deserialization would help.
A picture from the current values of the returning array (Not with the workaround):