diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index dbf59c141f..aeafac4a7e 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -230,8 +230,9 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer throw new RuntimeException(sprintf('The type "%s" has no mapped class for the abstract object "%s".', $type, $class)); } - $class = $mappedClass; - $reflectionClass = new \ReflectionClass($class); + if ($mappedClass !== $class) { + return $this->instantiateObject($data, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format); + } } return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 01b8950cb4..1b6e1b0a06 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping; +use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; @@ -235,6 +236,43 @@ class AbstractObjectNormalizerTest extends TestCase $this->assertInstanceOf(DummySecondChildQuux::class, $normalizedData->quux); } + public function testDenormalizeWithNestedDiscriminatorMap() + { + $classDiscriminatorResolver = new class() implements ClassDiscriminatorResolverInterface { + public function getMappingForClass(string $class): ?ClassDiscriminatorMapping + { + switch ($class) { + case AbstractDummy::class: + return new ClassDiscriminatorMapping('type', [ + 'foo' => AbstractDummyFirstChild::class, + ]); + case AbstractDummyFirstChild::class: + return new ClassDiscriminatorMapping('nested_type', [ + 'bar' => AbstractDummySecondChild::class, + ]); + default: + return null; + } + } + + public function getMappingForMappedObject($object): ?ClassDiscriminatorMapping + { + return null; + } + + public function getTypeForMappedObject($object): ?string + { + return null; + } + }; + + $normalizer = new AbstractObjectNormalizerDummy(null, null, null, $classDiscriminatorResolver); + + $denormalizedData = $normalizer->denormalize(['type' => 'foo', 'nested_type' => 'bar'], AbstractDummy::class); + + $this->assertInstanceOf(AbstractDummySecondChild::class, $denormalizedData); + } + /** * Test that additional attributes throw an exception if no metadata factory is specified. */