diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index e17042097fe3..9d0c45a6b0c4 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -222,7 +222,7 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a throw new NotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type)); } - if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]) || isset($this->defaultContext[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) { + if ((isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]) || isset($this->defaultContext[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) && !isset($context['not_normalizable_value_exceptions'])) { unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]); $context['not_normalizable_value_exceptions'] = []; $errors = &$context['not_normalizable_value_exceptions']; diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index da5ccc15e439..b0dc887cea40 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -1677,6 +1677,54 @@ public function testCollectDenormalizationErrorsDefaultContext() $serializer->denormalize($data, DummyWithVariadicParameter::class); } + + public function testDenormalizationFailsWithMultipleErrorsInDefaultContext() + { + $serializer = new Serializer( + [new DateTimeNormalizer(), new ObjectNormalizer()], + [], + [DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true] + ); + + $data = ['date' => '', 'unknown' => null]; + + try { + $serializer->denormalize($data, DummyEntityWithStringAndDateTime::class); + $this->fail('Expected PartialDenormalizationException was not thrown'); + } catch (PartialDenormalizationException $e) { + $this->assertIsArray($e->getErrors()); + $this->assertCount(2, $e->getErrors(), 'Expected two denormalization errors'); + + $exceptionsAsArray = array_map(function (NotNormalizableValueException $ex): array { + return [ + 'currentType' => $ex->getCurrentType(), + 'expectedTypes' => $ex->getExpectedTypes(), + 'path' => $ex->getPath(), + 'useMessageForUser' => $ex->canUseMessageForUser(), + 'message' => $ex->getMessage(), + ]; + }, $e->getErrors()); + + $expected = [ + [ + 'currentType' => 'null', + 'expectedTypes' => ['string'], + 'path' => 'bar', + 'useMessageForUser' => true, + 'message' => 'Failed to create object because the class misses the "bar" property.', + ], + [ + 'currentType' => 'string', + 'expectedTypes' => ['string'], + 'path' => 'date', + 'useMessageForUser' => true, + 'message' => 'The data is either not an string, an empty string, or null; you should pass a string that can be parsed with the passed format or a valid DateTime string.', + ], + ]; + + $this->assertSame($expected, $exceptionsAsArray); + } + } } class Model @@ -1743,6 +1791,15 @@ public function __construct($value) } } +class DummyEntityWithStringAndDateTime +{ + public function __construct( + public string $bar, + public \DateTimeInterface $date, + ) { + } +} + class DummyUnionType { /**