bug #37845 [Serializer] Fix variadic support when using type hints (fabpot)

This PR was merged into the 3.4 branch.

Discussion
----------

[Serializer] Fix variadic support when using type hints

| Q             | A
| ------------- | ---
| Branch?       | 3.4 <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | n/a <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT
| Doc PR        | n/a

Commits
-------

3fffa96928 [Serializer] Fix variadic support when using type hints
This commit is contained in:
Fabien Potencier 2020-08-16 10:23:32 +02:00
commit 688dbd9dab
3 changed files with 39 additions and 6 deletions

View File

@ -304,7 +304,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
*/
protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, $parameterName, $parameterData, array $context, $format = null)
{
if (null === $this->propertyTypeExtractor || null === $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) {
if ((method_exists($parameter, 'isVariadic') && $parameter->isVariadic()) || null === $this->propertyTypeExtractor || null === $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) {
return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format);
}

View File

@ -20,6 +20,7 @@ class VariadicConstructorTypedArgsDummy
$this->foo = $foo;
}
/** @return Dummy[] */
public function getFoo()
{
return $this->foo;

View File

@ -4,6 +4,8 @@ namespace Symfony\Component\Serializer\Tests\Normalizer;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassMetadata;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
@ -135,19 +137,49 @@ class AbstractNormalizerTest extends TestCase
}
/**
* @dataProvider getNormalizer
*
* @requires PHP 5.6
*/
public function testObjectWithVariadicConstructorTypedArguments()
public function testObjectWithVariadicConstructorTypedArguments(AbstractNormalizer $normalizer)
{
$normalizer = new PropertyNormalizer();
$normalizer->setSerializer(new Serializer([$normalizer]));
$data = ['foo' => [['foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz', 'qux' => 'Qux'], ['foo' => 'FOO', 'bar' => 'BAR', 'baz' => 'BAZ', 'qux' => 'QUX']]];
$dummy = $normalizer->denormalize($data, VariadicConstructorTypedArgsDummy::class);
$d1 = new Dummy();
$d1->foo = 'Foo';
$d1->bar = 'Bar';
$d1->baz = 'Baz';
$d1->qux = 'Quz';
$d2 = new Dummy();
$d2->foo = 'FOO';
$d2->bar = 'BAR';
$d2->baz = 'BAZ';
$d2->qux = 'QUZ';
$obj = new VariadicConstructorTypedArgsDummy($d1, $d2);
$serializer = new Serializer([$normalizer], [new JsonEncoder()]);
$normalizer->setSerializer($serializer);
$data = $serializer->serialize($obj, 'json');
$dummy = $normalizer->denormalize(json_decode($data, true), VariadicConstructorTypedArgsDummy::class);
$this->assertInstanceOf(VariadicConstructorTypedArgsDummy::class, $dummy);
$this->assertCount(2, $dummy->getFoo());
foreach ($dummy->getFoo() as $foo) {
$this->assertInstanceOf(Dummy::class, $foo);
}
$dummy = $serializer->deserialize($data, VariadicConstructorTypedArgsDummy::class, 'json');
$this->assertInstanceOf(VariadicConstructorTypedArgsDummy::class, $dummy);
$this->assertCount(2, $dummy->getFoo());
foreach ($dummy->getFoo() as $foo) {
$this->assertInstanceOf(Dummy::class, $foo);
}
}
public function getNormalizer()
{
$extractor = new PhpDocExtractor();
yield [new PropertyNormalizer()];
yield [new PropertyNormalizer(null, null, $extractor)];
yield [new ObjectNormalizer()];
yield [new ObjectNormalizer(null, null, null, $extractor)];
}
}