Skip to content

Commit 30f2213

Browse files
committed
[Serializer] Fix nested deserialization_path computation when there is no metadata for the attribute
1 parent 851007f commit 30f2213

File tree

3 files changed

+65
-19
lines changed

3 files changed

+65
-19
lines changed

Normalizer/AbstractObjectNormalizer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,12 @@ private function getAttributeNormalizationContext(object $object, string $attrib
239239
*/
240240
private function getAttributeDenormalizationContext(string $class, string $attribute, array $context): array
241241
{
242+
$context['deserialization_path'] = ($context['deserialization_path'] ?? false) ? $context['deserialization_path'].'.'.$attribute : $attribute;
243+
242244
if (null === $metadata = $this->getAttributeMetadata($class, $attribute)) {
243245
return $context;
244246
}
245247

246-
$context['deserialization_path'] = ($context['deserialization_path'] ?? false) ? $context['deserialization_path'].'.'.$attribute : $attribute;
247-
248248
return array_merge($context, $metadata->getDenormalizationContextForGroups($this->getGroups($context)));
249249
}
250250

Tests/Fixtures/Php74Full.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ final class Php74Full
2929
public array $collection;
3030
public Php74FullWithConstructor $php74FullWithConstructor;
3131
public DummyMessageInterface $dummyMessage;
32+
/** @var TestFoo[] $nestedArray */
33+
public TestFoo $nestedObject;
3234
}
3335

3436

@@ -38,3 +40,8 @@ public function __construct($constructorArgument)
3840
{
3941
}
4042
}
43+
44+
final class TestFoo
45+
{
46+
public int $int;
47+
}

Tests/SerializerTest.php

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,12 @@ public function testDeserializeAndUnwrap()
739739
);
740740
}
741741

742-
/** @requires PHP 7.4 */
743-
public function testCollectDenormalizationErrors()
742+
/**
743+
* @dataProvider provideCollectDenormalizationErrors
744+
*
745+
* @requires PHP 7.4
746+
*/
747+
public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMetadataFactory)
744748
{
745749
$json = '
746750
{
@@ -764,10 +768,12 @@ public function testCollectDenormalizationErrors()
764768
],
765769
"php74FullWithConstructor": {},
766770
"dummyMessage": {
771+
},
772+
"nestedObject": {
773+
"int": "string"
767774
}
768775
}';
769776

770-
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
771777
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
772778

773779
$serializer = new Serializer(
@@ -777,7 +783,7 @@ public function testCollectDenormalizationErrors()
777783
new DateTimeZoneNormalizer(),
778784
new DataUriNormalizer(),
779785
new UidNormalizer(),
780-
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
786+
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, $classMetadataFactory ? new ClassDiscriminatorFromClassMetadata($classMetadataFactory) : null),
781787
],
782788
['json' => new JsonEncoder()]
783789
);
@@ -913,22 +919,45 @@ public function testCollectDenormalizationErrors()
913919
'useMessageForUser' => true,
914920
'message' => 'Failed to create object because the object miss the "constructorArgument" property.',
915921
],
922+
$classMetadataFactory ?
923+
[
924+
'currentType' => 'null',
925+
'expectedTypes' => [
926+
'string',
927+
],
928+
'path' => 'dummyMessage.type',
929+
'useMessageForUser' => false,
930+
'message' => 'Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface".',
931+
] :
932+
[
933+
'currentType' => 'array',
934+
'expectedTypes' => [
935+
DummyMessageInterface::class,
936+
],
937+
'path' => 'dummyMessage',
938+
'useMessageForUser' => false,
939+
'message' => 'The type of the "dummyMessage" attribute for class "Symfony\Component\Serializer\Tests\Fixtures\Php74Full" must be one of "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface" ("array" given).',
940+
],
916941
[
917-
'currentType' => 'null',
942+
'currentType' => 'string',
918943
'expectedTypes' => [
919-
'string',
944+
'int',
920945
],
921-
'path' => 'dummyMessage.type',
922-
'useMessageForUser' => false,
923-
'message' => 'Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface".',
946+
'path' => 'nestedObject[int]',
947+
'useMessageForUser' => true,
948+
'message' => 'The type of the key "int" must be "int" ("string" given).',
924949
],
925950
];
926951

927952
$this->assertSame($expected, $exceptionsAsArray);
928953
}
929954

930-
/** @requires PHP 7.4 */
931-
public function testCollectDenormalizationErrors2()
955+
/**
956+
* @dataProvider provideCollectDenormalizationErrors
957+
*
958+
* @requires PHP 7.4
959+
*/
960+
public function testCollectDenormalizationErrors2(?ClassMetadataFactory $classMetadataFactory)
932961
{
933962
$json = '
934963
[
@@ -940,13 +969,12 @@ public function testCollectDenormalizationErrors2()
940969
}
941970
]';
942971

943-
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
944972
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
945973

946974
$serializer = new Serializer(
947975
[
948976
new ArrayDenormalizer(),
949-
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
977+
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, $classMetadataFactory ? new ClassDiscriminatorFromClassMetadata($classMetadataFactory) : null),
950978
],
951979
['json' => new JsonEncoder()]
952980
);
@@ -999,17 +1027,20 @@ public function testCollectDenormalizationErrors2()
9991027
$this->assertSame($expected, $exceptionsAsArray);
10001028
}
10011029

1002-
/** @requires PHP 8.0 */
1003-
public function testCollectDenormalizationErrorsWithConstructor()
1030+
/**
1031+
* @dataProvider provideCollectDenormalizationErrors
1032+
*
1033+
* @requires PHP 8.0
1034+
*/
1035+
public function testCollectDenormalizationErrorsWithConstructor(?ClassMetadataFactory $classMetadataFactory)
10041036
{
10051037
$json = '{"bool": "bool"}';
10061038

1007-
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
10081039
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
10091040

10101041
$serializer = new Serializer(
10111042
[
1012-
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
1043+
new ObjectNormalizer($classMetadataFactory, null, null, $extractor, $classMetadataFactory ? new ClassDiscriminatorFromClassMetadata($classMetadataFactory) : null),
10131044
],
10141045
['json' => new JsonEncoder()]
10151046
);
@@ -1050,6 +1081,14 @@ public function testCollectDenormalizationErrorsWithConstructor()
10501081

10511082
$this->assertSame($expected, $exceptionsAsArray);
10521083
}
1084+
1085+
public function provideCollectDenormalizationErrors()
1086+
{
1087+
return [
1088+
[null],
1089+
[new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()))],
1090+
];
1091+
}
10531092
}
10541093

10551094
class Model

0 commit comments

Comments
 (0)