Skip to content

Commit 49de027

Browse files
bug symfony#50024 [Serializer] Fix denormalization of object with typed constructor arg (not castable) and with COLLECT_DENORMALIZATION_ERRORS (lyrixx)
This PR was merged into the 5.4 branch. Discussion ---------- [Serializer] Fix denormalization of object with typed constructor arg (not castable) and with COLLECT_DENORMALIZATION_ERRORS | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | | License | MIT | Doc PR | There is already a test for constructor instantiation but it worked "by chance". The test is `testCollectDenormalizationErrorsWithConstructor`. It worked because `$reflectionClass->newInstanceArgs($params)` works if one give a `string` value that should fit in a `bool` type. PHP casts automatically the value for us. (see: https://3v4l.org/GYr0T) Now we ensure to not throw an exception if the instantiation cannot be done. The mismatch is already collected few lines above, so there nothing to do more Commits ------- df2e7cd [Serializer] Fix denormalization of object with typed constructor arg (not castable) and with COLLECT_DENORMALIZATION_ERRORS
2 parents 547e876 + df2e7cd commit 49de027

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,15 @@ protected function instantiateObject(array &$data, string $class, array &$contex
417417
}
418418

419419
if ($constructor->isConstructor()) {
420-
return $reflectionClass->newInstanceArgs($params);
420+
try {
421+
return $reflectionClass->newInstanceArgs($params);
422+
} catch (\TypeError $th) {
423+
if (!isset($context['not_normalizable_value_exceptions'])) {
424+
throw $th;
425+
}
426+
427+
return $reflectionClass->newInstanceWithoutConstructor();
428+
}
421429
} else {
422430
return $constructor->invokeArgs(null, $params);
423431
}

src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class Php74Full
2828
/** @var Php74Full[] */
2929
public array $collection;
3030
public Php74FullWithConstructor $php74FullWithConstructor;
31+
public Php74FullWithTypedConstructor $php74FullWithTypedConstructor;
3132
public DummyMessageInterface $dummyMessage;
3233
/** @var TestFoo[] $nestedArray */
3334
public TestFoo $nestedObject;
@@ -43,6 +44,13 @@ public function __construct($constructorArgument)
4344
}
4445
}
4546

47+
final class Php74FullWithTypedConstructor
48+
{
49+
public function __construct(float $something)
50+
{
51+
}
52+
}
53+
4654
final class TestFoo
4755
{
4856
public int $int;

src/Symfony/Component/Serializer/Tests/SerializerTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,9 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet
852852
}
853853
],
854854
"php74FullWithConstructor": {},
855+
"php74FullWithTypedConstructor": {
856+
"something": "not a float"
857+
},
855858
"dummyMessage": {
856859
},
857860
"nestedObject": {
@@ -1005,6 +1008,15 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet
10051008
'useMessageForUser' => true,
10061009
'message' => 'Failed to create object because the class misses the "constructorArgument" property.',
10071010
],
1011+
[
1012+
'currentType' => 'string',
1013+
'expectedTypes' => [
1014+
'float',
1015+
],
1016+
'path' => 'php74FullWithTypedConstructor',
1017+
'useMessageForUser' => false,
1018+
'message' => 'The type of the "something" attribute for class "Symfony\Component\Serializer\Tests\Fixtures\Php74FullWithTypedConstructor" must be one of "float" ("string" given).',
1019+
],
10081020
$classMetadataFactory ?
10091021
[
10101022
'currentType' => 'null',

0 commit comments

Comments
 (0)