8000 bug #49537 [Serializer] Unexpected value should throw UnexpectedValue… · symfony/symfony@651b9d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 651b9d6

Browse files
bug #49537 [Serializer] Unexpected value should throw UnexpectedValueException (ThomasTr)
This PR was merged into the 5.4 branch. Discussion ---------- [Serializer] Unexpected value should throw UnexpectedValueException | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | See my recently started discussion here: #49535 | License | MIT | Doc PR | NA If a DateTime field to be serialised has a data type other than string (e.g. a serialised DateTime as array), a TypeException is thrown. This exception cannot be caught by a try/catch around the serializer. This fix throws a NotNormalizableValueException that appears cleanly at the corresponding field. This is my first pull request, please be kind to me :) Commits ------- af34c52 [Serializer] Unexpected value should throw UnexpectedValueException
2 parents 1a5e19b + af34c52 commit 651b9d6

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,34 +91,36 @@ public function denormalize($data, string $type, string $format = null, array $c
9191
$dateTimeFormat = $context[self::FORMAT_KEY] ?? null;
9292
$timezone = $this->getTimezone($context);
9393

94-
if (null === $data || (\is_string($data) && '' === trim($data))) {
95-
throw NotNormalizableValueException::createForUnexpectedDataType('The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.', $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true);
94+
if (null === $data || !\is_string($data) || '' === trim($data)) {
95+
throw NotNormalizableValueException::createForUnexpectedDataType('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.', $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true);
9696
}
9797

98-
if (null !== $dateTimeFormat) {
99-
$object = \DateTime::class === $type ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone);
98+
try {
99+
if (null !== $dateTimeFormat) {
100+
$object = \DateTime::class === $type ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone);
100101

101-
if (false !== $object) {
102-
return $object;
103-
}
102+
if (false !== $object) {
103+
return $object;
104+
}
104105

105-
$dateTimeErrors = \DateTime::class === $type ? \DateTime::getLastErrors() : \DateTimeImmutable::getLastErrors();
106+
$dateTimeErrors = \DateTime::class === $type ? \DateTime::getLastErrors() : \DateTimeImmutable::getLastErrors();
106107

107-
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count'])."\n".implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors'])), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true);
108-
}
108+
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count'])."\n".implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors'])), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true);
109+
}
109110

110-
$defaultDateTimeFormat = $this->defaultContext[self::FORMAT_KEY] ?? null;
111+
$defaultDateTimeFormat = $this->defaultContext[self::FORMAT_KEY] ?? null;
111112

112-
if (null !== $defaultDateTimeFormat) {
113-
$object = \DateTime::class === $type ? \DateTime::createFromFormat($defaultDateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($defaultDateTimeFormat, $data, $timezone);
113+
if (null !== $defaultDateTimeFormat) {
114+
$object = \DateTime::class === $type ? \DateTime::createFromFormat($defaultDateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($defaultDateTimeFormat, $data, $timezone);
114115

115-
if (false !== $object) {
116-
return $object;
116+
if (false !== $object) {
117+
return $object;
118+
}
117119
}
118-
}
119120

120-
try {
121121
return \DateTime::class === $type ? new \DateTime($data, $timezone) : new \DateTimeImmutable($data, $timezone);
122+
} catch (NotNormalizableValueException $e) {
123+
throw $e;
122124
} catch (\Exception $e) {
123125
throw NotNormalizableValueException::createForUnexpectedDataType($e->getMessage(), $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, false, $e->getCode(), $e);
124126
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,24 +243,31 @@ public function testDenormalizeInvalidDataThrowsException()
243243
$this->normalizer->denormalize('invalid date', \DateTimeInterface::class);
244244
}
245245

246+
public function testDenormalizeWrongTypeThrowsException()
247+
{
248+
$this->expectException(UnexpectedValueException::class);
249+
$this->expectExceptionMessage('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.');
250+
$this->normalizer->denormalize(['date' => '2023-03-03 00:00:00.000000', 'timezone_type' => 1, 'timezone' => '+01:00'], \DateTimeInterface::class);
251+
}
252+
246253
public function testDenormalizeNullThrowsException()
247254
{
248255
$this->expectException(UnexpectedValueException::class);
249-
$this->expectExceptionMessage('The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.');
256+
$this->expectExceptionMessage('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.');
250257
$this->normalizer->denormalize(null, \DateTimeInterface::class);
251258
}
252259

253260
public function testDenormalizeEmptyStringThrowsException()
254261
{
255262
$this->expectException(UnexpectedValueException::class);
256-
$this->expectExceptionMessage('The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.');
263+
$this->expectExceptionMessage('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.');
257264
$this->normalizer->denormalize('', \DateTimeInterface::class);
258265
}
259266

260267
public function testDenormalizeStringWithSpacesOnlyThrowsAnException()
261268
{
262269
$this->expectException(UnexpectedValueException::class);
263-
$this->expectExceptionMessage('The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.');
270+
$this->expectExceptionMessage('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.');
264271
$this->normalizer->denormalize(' ', \DateTimeInterface::class);
265272
}
266273

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet
943943
],
944944
'pat 8EE5 h' => 'dateTime',
945945
'useMessageForUser' => true,
946-
'message' => 'The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.',
946+
'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.',
947947
],
948948
[
949949
'currentType' => 'null',
@@ -952,7 +952,7 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet
952952
],
953953
'path' => 'dateTimeImmutable',
954954
'useMessageForUser' => true,
955-
'message' => 'The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.',
955+
'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.',
956956
],
957957
[
958958
'currentType' => 'null',

0 commit comments

Comments
 (0)
0