-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Description
Symfony version(s) affected: 4.4.7 (probably lower and higher also)
Description
Could someone explain me why PropertyNormalizer doesn't support DiscriminatorMap ?
Everything works fine if I use ObjectNormalizer but if I choose PropertyNormalizer instead of ObjectNormalizer and do serialization or desialization as a result this functionality doesn't work. However both normalizers have one common parent class this is AbstractObjectNormalizer and if you look at the constructor declaration you will see a dependency on ClassDiscriminatorResolverInterface but PropertyNormalizer doesn't support a "discriminator class mapping".
As seems to me something is wrong with Barbora-Liskov substitution principle. Am I right, or were there reasons for that ?
How to reproduce
// ...
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Serializer;
/**
* @DiscriminatorMap(typeProperty="type", mapping={
* "github"="GitHubCodeRepository",
* "bitbucket"="BitBucketCodeRepository"
* })
*/
interface CodeRepository {}
class GitHubCodeRepository implements CodeRepository
{
private $url;
}
class BitBucketCodeRepository implements CodeRepository
{
private $url;
}
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$discriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
$serializer = new Serializer(
[new PropertyNormalizer($classMetadataFactory, null, null, $discriminator)],
['json' => new JsonEncoder()]
);
$serialized = $serializer->serialize(new GitHubCodeRepository(), 'json');
// actual: {"type":null, "url":"null"}
// expected: {"type":"github"}
$repository = $serializer->deserialize($serialized, CodeRepository::class, 'json');
// actual:
// exception: \Symfony\Component\Serializer\Exception\NotNormalizableValueException
// message: Could not denormalize object of type "CodeRepository", no supporting normalizer found.