8000 bug #50480 [Serializer] Fix discriminator map not working with `Abstr… · symfony/symfony@e901262 · GitHub
[go: up one dir, main page]

Skip to content

Commit e901262

Browse files
bug #50480 [Serializer] Fix discriminator map not working with AbstractNormalizer::OBJECT_TO_POPULATE (HypeMC)
This PR was merged into the 6.2 branch. Discussion ---------- [Serializer] Fix discriminator map not working with `AbstractNormalizer::OBJECT_TO_POPULATE` | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #50472 | License | MIT | Doc PR | - Ensures that the mapped class is taken from `AbstractNormalizer::OBJECT_TO_POPULATE` if it's set. Commits ------- da82f53 [Serializer] Fix discriminator map not working with `AbstractNormalizer::OBJECT_TO_POPULATE`
2 parents 9a3b651 + da82f53 commit e901262

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed 8000

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,10 @@ private function removeNestedValue(array $path, array $data): array
780780
*/
781781
private function getMappedClass(array $data, string $class, array $context): string
782782
{
783+
if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) {
784+
return $object::class;
785+
}
786+
783787
if (!$mapping = $this->classDiscriminatorResolver?->getMappingForClass($class)) {
784788
return $class;
785789
}

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
3535
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
3636
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
37+
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
3738
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
3839
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
3940
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
@@ -44,6 +45,7 @@
4445
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummy;
4546
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummyFirstChild;
4647
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummySecondChild;
48+
use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux;
4749
use Symfony\Component\Serializer\Tests\Fixtures\DummySecondChildQuux;
4850
use Symfony\Component\Serializer\Tests\Normalizer\Features\ObjectDummyWithContextAttribute;
4951

@@ -480,6 +482,61 @@ public function hasMetadataFor($value): bool
480482
$this->assertInstanceOf(DummySecondChildQuux::class, $normalizedData->quux);
481483
}
482484

485+
public function testDenormalizeWithDiscriminatorMapAndObjectToPopulateUsesCorrectClassname()
486+
{
487+
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
488+
489+
$loaderMock = new class() implements ClassMetadataFactoryInterface {
490+
public function getMetadataFor($value): ClassMetadataInterface
491+
{
492+
if (AbstractDummy::class === $value) {
493+
return new ClassMetadata(
494+
AbstractDummy::class,
495+
new ClassDiscriminatorMapping('type', [
496+
'first' => AbstractDummyFirstChild::class,
497+
'second' => AbstractDummySecondChild::class,
498+
])
499+
);
500+
}
501+
502+
throw new InvalidArgumentException();
503+
}
504+
505+
public function hasMetadataFor($value): bool
506+
{
507+
return AbstractDummy::class === $value;
508+
}
509+
};
510+
511+
$discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock);
512+
$normalizer = new AbstractObjectNormalizerDummy($factory, null, new PhpDocExtractor(), $discriminatorResolver);
513+
$serializer = new Serializer([$normalizer]);
514+
$normalizer->setSerializer($serializer);
515+
516+
$data = [
517+
'foo' => 'foo',
518+
'quux' => ['value' => 'quux'],
519+
];
520+
521+
$normalizedData1 = $normalizer->denormalize($data + ['bar' => 'bar'], AbstractDummy::class, 'any', [
522+
AbstractNormalizer::OBJECT_TO_POPULATE => new AbstractDummyFirstChild('notfoo', 'notbar'),
523+
]);
524+
$this->assertInstanceOf(AbstractDummyFirstChild::class, $normalizedData1);
525+
$this->assertSame('foo', $normalizedData1->foo);
526+
$this->assertSame('notbar', $normalizedData1->bar);
527+
$this->assertInstanceOf(DummyFirstChildQuux::class, $normalizedData1->quux);
528+
$this->assertSame('quux', $normalizedData1->quux->getValue());
529+
530+
$normalizedData2 = $normalizer->denormalize($data + ['baz' => 'baz'], AbstractDummy::class, 'any', [
531+
AbstractNormalizer::OBJECT_TO_POPULATE => new AbstractDummySecondChild('notfoo', 'notbaz'),
532+
]);
533+
$this->assertInstanceOf(AbstractDummySecondChild::class, $normalizedData2);
534+
$this->assertSame('foo', $normalizedData2->foo);
535+
$this->assertSame('baz', $normalizedData2->baz);
536+
$this->assertInstanceOf(DummySecondChildQuux::class, $normalizedData2->quux);
537+
$this->assertSame('quux', $normalizedData2->quux->getValue());
538+
}
539+
483540
public function testDenormalizeWithNestedDiscriminatorMap()
484541
{
485542
$classDiscriminatorResolver = new class() implements ClassDiscriminatorResolverInterface {

0 commit comments

Comments
 (0)
0