8000 [Serializer] Fix SerializedPath not working with constructor arguments · symfony/symfony@e13aa7a · GitHub
[go: up one dir, main page]

Skip to content

Commit e13aa7a

Browse files
committed
[Serializer] Fix SerializedPath not working with constructor arguments
1 parent 2407467 commit e13aa7a

File tree

10 files changed

+165
-4
lines changed

10 files changed

+165
-4
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,8 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
320320
$extraAttributes = [];
321321

322322
$reflectionClass = new \ReflectionClass($type);
323-
$object = $this->instantiateObject($normalizedData, $type, $context, $reflectionClass, $allowedAttributes, $format);
324-
$resolvedClass = $this->objectClassResolver ? ($this->objectClassResolver)($object) : $object::class;
325323

326-
$nestedAttributes = $this->getNestedAttributes($resolvedClass);
324+
$nestedAttributes = $this->getNestedAttributes($reflectionClass->getName());
327325
$nestedData = [];
328326
$propertyAccessor = PropertyAccess::createPropertyAccessor();
329327
foreach ($nestedAttributes as $property => $serializedPath) {
@@ -336,6 +334,9 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
336334

337335
$normalizedData = array_merge($normalizedData, $nestedData);
338336

337+
$object = $this->instantiateObject($normalizedData, $type, $context, $reflectionClass, $allowedAttributes, $format);
338+
$resolvedClass = $this->objectClassResolver ? ($this->objectClassResolver)($object) : $object::class;
339+
339340
foreach ($normalizedData as $attribute => $value) {
340341
if ($this->nameConverter) {
341342
$notConverted = $attribute;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures\Annotations;
13+
14+
use Symfony\Component\Serializer\Annotation\SerializedPath;
15+
16+
class SerializedPathInConstructorDummy
17+
{
18+
public function __construct(
19+
/**
20+
* @SerializedPath("[one][two]")
21+
*/
22+
public $three,
23+
) {
24+
}
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures\Attributes;
13+
14+
use Symfony\Component\Serializer\Annotation\SerializedPath;
15+
16+
class SerializedPathInConstructorDummy
17+
{
18+
public function __construct(
19+
#[SerializedPath('[one][two]')] public $three,
20+
) {
21+
}
22+
}

src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
<attribute name="seven" serialized-path="[three][four]" />
3131
</class>
3232

33+
<class name="Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathInConstructorDummy">
34+
<attribute name="three" serialized-path="[one][two]" />
35+
</class>
36+
3337
<class name="Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummy">
3438
<discriminator-map type-property="type">
3539
<mapping type="first" class="Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummyFirstChild" />

src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
serialized_path: '[one][two]'
2323
seven:
2424
serialized_path: '[three][four]'
25+
'Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathInConstructorDummy':
26+
attributes:
27+
three:
28+
serialized_path: '[one][two]'
2529
'Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummy':
2630
discriminator_map:
2731
type_property: type

src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryCompilerTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\MaxDepthDummy;
2020
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedNameDummy;
2121
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathDummy;
22+
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathInConstructorDummy;
2223
use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
2324

2425
final class ClassMetadataFactoryCompilerTest extends TestCase
@@ -46,18 +47,20 @@ public function testItDumpMetadata()
4647
$maxDepthDummyMetadata = $classMetatadataFactory->getMetadataFor(MaxDepthDummy::class);
4748
$serializedNameDummyMetadata = $classMetatadataFactory->getMetadataFor(SerializedNameDummy::class);
4849
$serializedPathDummyMetadata = $classMetatadataFactory->getMetadataFor(SerializedPathDummy::class);
50+
$serializedPathInConstructorDummyMetadata = $classMetatadataFactory->getMetadataFor(SerializedPathInConstructorDummy::class);
4951

5052
$code = (new ClassMetadataFactoryCompiler())->compile([
5153
$dummyMetadata,
5254
$maxDepthDummyMetadata,
5355
$serializedNameDummyMetadata,
5456
$serializedPathDummyMetadata,
57+
$serializedPathInConstructorDummyMetadata,
5558
]);
5659

5760
file_put_contents($this->dumpPath, $code);
5861
$compiledMetadata = require $this->dumpPath;
5962

60-
$this->assertCount(4, $compiledMetadata);
63+
$this->assertCount(5, $compiledMetadata);
6164

6265
$this->assertArrayHasKey(Dummy::class, $compiledMetadata);
6366
$this->assertEquals([
@@ -99,5 +102,13 @@ public function testItDumpMetadata()
99102
],
100103
null,
101104
], $compiledMetadata[SerializedPathDummy::class]);
105+
106+
$this->assertArrayHasKey(SerializedPathInConstructorDummy::class, $compiledMetadata);
107+
$this->assertEquals([
108+
[
109+
'three' => [[], null, null, '[one][two]'],
110+
],
111+
null,
112+
], $compiledMetadata[SerializedPathInConstructorDummy::class]);
102113
}
103114
}

src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTestCase.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ public function testLoadSerializedPath()
103103
$this->assertEquals(new PropertyPath('[three][four]'), $attributesMetadata['seven']->getSerializedPath());
104104
}
105105

106+
public function testLoadSerializedPathInConstructor()
107+
{
108+
$classMetadata = new ClassMetadata($this->getNamespace().'\SerializedPathInConstructorDummy');
109+
$this->loader->loadClassMetadata($classMetadata);
110+
111+
$attributesMetadata = $classMetadata->getAttributesMetadata();
112+
$this->assertEquals(new PropertyPath('[one][two]'), $attributesMetadata['three']->getSerializedPath());
113+
}
114+
106115
public function testLoadClassMetadataAndMerge()
107116
{
108117
$classMetadata = new ClassMetadata($this->getNamespace().'\GroupDummy');

src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ public function testSerializedPath()
9494
$this->assertEquals('[three][four]', $attributesMetadata['seven']->getSerializedPath());
9595
}
9696

97+
public function testSerializedPathInConstructor()
98+
{
99+
$classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathInConstructorDummy');
100+
$this->loader->loadClassMetadata($classMetadata);
101+
102+
$attributesMetadata = $classMetadata->getAttributesMetadata();
103+
$this->assertEquals('[one][two]', $attributesMetadata['three']->getSerializedPath());
104+
}
105+
97106
public function testLoadDiscriminatorMap()
98107
{
99108
$classMetadata = new ClassMetadata(AbstractDummy::class);

src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ public function testSerializedPath()
108108
$this->assertEquals(new PropertyPath('[three][four]'), $attributesMetadata['seven']->getSerializedPath());
109109
}
110110

111+
public function testSerializedPathInConstructor()
112+
{
113+
$classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathInConstructorDummy');
114+
$this->loader->loadClassMetadata($classMetadata);
115+
116+
$attributesMetadata = $classMetadata->getAttributesMetadata();
117+
$this->assertEquals(new PropertyPath('[one][two]'), $attributesMetadata['three']->getSerializedPath());
118+
}
119+
111120
public function testLoadDiscriminatorMap()
112121
{
113122
$classMetadata = new ClassMetadata(AbstractDummy::class);

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,26 @@ public function testDenormalizeWithNestedAttributesDuplicateKeys()
171171
$normalizer->denormalize($data, DuplicateKeyNestedDummy::class, 'any');
172172
}
173173

174+
public function testDenormalizeWithNestedAttributesInConstructor()
175+
{
176+
$normalizer = new AbstractObjectNormalizerWithMetadata();
177+
$data = [
178+
'one' => [
179+
'two' => [
180+
'three' => 'foo',
181+
],
182+
'four' => 'quux',
183+
],
184+
'foo' => 'notfoo',
185+
'baz' => 'baz',
186+
];
187+
$test = $normalizer->denormalize($data, NestedDummyWithConstructor::class, 'any');
188+
$this->assertSame('baz', $test->baz);
189+
$this->assertSame('foo', $test->foo);
190+
$this->assertSame('quux', $test->quux);
191+
$this->assertSame('notfoo', $test->notfoo);
192+
}
193+
174194
public function testNormalizeWithNestedAttributesMixingArrayTypes()
175195
{
176196
$this->expectException(LogicException::class);
@@ -236,6 +256,30 @@ public function testNormalizeWithNestedAttributesWithoutMetadata()
236256
$this->assertSame($data, $test);
237257
}
238258

259+
public function testNormalizeWithNestedAttributesInConstructor()
260+
{
261+
$foobar = new NestedDummyWithConstructor(
262+
'foo',
263+
'quux',
264+
'notfoo',
265+
'baz',
266+
);
267+
$data = [
268+
'one' => [
269+
'two' => [
270+
'three' => 'foo',
271+
],
272+
'four' => 'quux',
273+
],
274+
'foo' => 'notfoo',
275+
'baz' => 'baz',
276+
];
277+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
278+
$normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory));
279+
$test = $normalizer->normalize($foobar, 'any');
280+
$this->assertSame($data, $test);
281+
}
282+
239283
public function testDenormalizeCollectionDecodedFromXmlWithOneChild()
240284
{
241285
$denormalizer = $this->getDenormalizerForDummyCollection();
@@ -661,6 +705,29 @@ class NestedDummy
661705
public $baz;
662706
}
663707

708+
class NestedDummyWithConstructor
709+
{
710+
public function __construct(
711+
/**
712+
* @SerializedPath("[one][two][three]")
713+
*/
714+
public $foo,
715+
716+
/**
717+
* @SerializedPath("[one][four]")
718+
*/
719+
public $quux,
720+
721+
/**
722+
* @SerializedPath("[foo]")
723+
*/
724+
public $notfoo,
725+
726+
public $baz,
727+
) {
728+
}
729+
}
730+
664731
class DuplicateKeyNestedDummy
665732
{
666733
/**

0 commit comments

Comments
 (0)
0