Skip to content

Commit 4690cbf

Browse files
committed
Add AbstractObjectNormalizer::ENABLE_TYPE_CONVERSION for scalar type transformation
1 parent eee7e8f commit 4690cbf

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CHANGELOG
1111
* Make `ProblemNormalizer` give details about Messenger's `ValidationFailedException`
1212
* Add `XmlEncoder::CDATA_WRAPPING` context option
1313
* Deprecate `AnnotationLoader`, use `AttributeLoader` instead
14+
* Add `AbstractObjectNormalizer::ENABLE_TYPE_CONVERSION` for scalar type transformation
1415

1516
6.3
1617
---

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

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
5656
*/
5757
public const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
5858

59+
/**
60+
* While denormalizing, convert scalar types to the expected type.
61+
*
62+
* Enabled by default for the XML and CSV format, because all basic datatypes are represented as strings.
63+
*/
64+
public const ENABLE_TYPE_CONVERSION = 'enable_type_conversion';
65+
5966
/**
6067
* Flag to control whether fields with the value `null` should be output
6168
* when normalizing or omitted.
@@ -290,8 +297,6 @@ abstract protected function extractAttributes(object $object, string $format = n
290297

291298
/**
292299
* Gets the attribute value.
293-
*
294-
* @return mixed
295300
*/
296301
abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []);
297302

@@ -305,9 +310,6 @@ public function supportsDenormalization(mixed $data, string $type, string $forma
305310
return class_exists($type) || (interface_exists($type, false) && null !== $this->classDiscriminatorResolver?->getMappingForClass($type));
306311
}
307312

308-
/**
309-
* @return mixed
310-
*/
311313
public function denormalize(mixed $data, string $type, string $format = null, array $context = [])
312314
{
313315
if (!isset($context['cache_key'])) {
@@ -320,6 +322,10 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
320322
return null;
321323
}
322324

325+
if (!isset($context[self::ENABLE_TYPE_CONVERSION]) && (XmlEncoder::FORMAT === $format || CsvEncoder::FORMAT === $format)) {
326+
$context[self::ENABLE_TYPE_CONVERSION] = true;
327+
}
328+
323329
$allowedAttributes = $this->getAllowedAttributes($type, $context, true);
324330
$normalizedData = $this->prepareForDenormalization($data);
325331
$extraAttributes = [];
@@ -434,11 +440,16 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
434440
$isUnionType = \count($types) > 1;
435441
$extraAttributesException = null;
436442
$missingConstructorArgumentsException = null;
443+
$hasNonObjectType = false;
444+
$isUnionTypeOrNullable = $isUnionType;
445+
437446
foreach ($types as $type) {
438447
if (null === $data && $type->isNullable()) {
439448
return null;
440449
}
441450

451+
$isUnionTypeOrNullable = $isUnionTypeOrNullable ?: $type->isNullable();
452+
$hasNonObjectType = $hasNonObjectType ?: Type::BUILTIN_TYPE_OBJECT !== $type->getBuiltinType();
442453
$collectionValueType = $type->isCollection() ? $type->getCollectionValueTypes()[0] ?? null : null;
443454

444455
// Fix a collection that contains the only one element
@@ -456,7 +467,7 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
456467
// In XML and CSV all basic datatypes are represented as strings, it is e.g. not possible to determine,
457468
// if a value is meant to be a string, float, int or a boolean value from the serialized representation.
458469
// That's why we have to transform the values, if one of these non-string basic datatypes is expected.
459-
if (\is_string($data) && (XmlEncoder::FORMAT === $format || CsvEncoder::FORMAT === $format)) {
470+
if (\is_string($data) && ($context[self::ENABLE_TYPE_CONVERSION] ?? false)) {
460471
if ('' === $data) {
461472
if (Type::BUILTIN_TYPE_ARRAY === $builtinType = $type->getBuiltinType()) {
462473
return [];
@@ -564,17 +575,17 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
564575
return $data;
565576
}
566577
} catch (NotNormalizableValueException|InvalidArgumentException $e) {
567-
if (!$isUnionType) {
578+
if (!$isUnionTypeOrNullable) {
568579
throw $e;
569580
}
570581
} catch (ExtraAttributesException $e) {
571-
if (!$isUnionType) {
582+
if (!$isUnionTypeOrNullable) {
572583
throw $e;
573584
}
574585

575586
$extraAttributesException ??= $e;
576587
} catch (MissingConstructorArgumentsException $e) {
577-
if (!$isUnionType) {
588+
if (!$isUnionTypeOrNullable) {
578589
throw $e;
579590
}
580591

@@ -590,6 +601,12 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
590601
throw $missingConstructorArgumentsException;
591602
}
592603

604+
if ('' === $data && !$hasNonObjectType && ($context[self::ENABLE_TYPE_CONVERSION] ?? false)) {
605+
return null;
606+
} elseif (!$isUnionType && isset($e)) {
607+
throw $e;
608+
}
609+
593610
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ?? $this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ?? false) {
594611
return $data;
595612
}

0 commit comments

Comments
 (0)