diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 5a8a2989b47..7c12bf211d6 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -883,6 +883,7 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); $types = $propertyMetadata->getBuiltinTypes() ?? []; $isMultipleTypes = \count($types) > 1; + $denormalizationException = null; foreach ($types as $type) { if (null === $value && ($type->isNullable() || ($context[static::DISABLE_TYPE_ENFORCEMENT] ?? false))) { @@ -908,7 +909,18 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value $context['resource_class'] = $resourceClass; unset($context['uri_variables']); - return $this->denormalizeCollection($attribute, $propertyMetadata, $type, $resourceClass, $value, $format, $context); + try { + return $this->denormalizeCollection($attribute, $propertyMetadata, $type, $resourceClass, $value, $format, $context); + } catch (NotNormalizableValueException $e) { + // union/intersect types: try the next type, if not valid, an exception will be thrown at the end + if ($isMultipleTypes) { + $denormalizationException ??= $e; + + continue; + } + + throw $e; + } } if ( @@ -918,7 +930,18 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value $resourceClass = $this->resourceClassResolver->getResourceClass(null, $className); $childContext = $this->createChildContext($this->createOperationContext($context, $resourceClass), $attribute, $format); - return $this->denormalizeRelation($attribute, $propertyMetadata, $resourceClass, $value, $format, $childContext); + try { + return $this->denormalizeRelation($attribute, $propertyMetadata, $resourceClass, $value, $format, $childContext); + } catch (NotNormalizableValueException $e) { + // union/intersect types: try the next type, if not valid, an exception will be thrown at the end + if ($isMultipleTypes) { + $denormalizationException ??= $e; + + continue; + } + + throw $e; + } } if ( @@ -933,7 +956,18 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value unset($context['resource_class'], $context['uri_variables']); - return $this->serializer->denormalize($value, $className.'[]', $format, $context); + try { + return $this->serializer->denormalize($value, $className.'[]', $format, $context); + } catch (NotNormalizableValueException $e) { + // union/intersect types: try the next type, if not valid, an exception will be thrown at the end + if ($isMultipleTypes) { + $denormalizationException ??= $e; + + continue; + } + + throw $e; + } } if (null !== $className = $type->getClassName()) { @@ -943,7 +977,18 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value unset($context['resource_class'], $context['uri_variables']); - return $this->serializer->denormalize($value, $className, $format, $context); + try { + return $this->serializer->denormalize($value, $className, $format, $context); + } catch (NotNormalizableValueException $e) { + // union/intersect types: try the next type, if not valid, an exception will be thrown at the end + if ($isMultipleTypes) { + $denormalizationException ??= $e; + + continue; + } + + throw $e; + } } /* From @see AbstractObjectNormalizer::validateAndDenormalize() */ @@ -1019,6 +1064,10 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value } } + if ($denormalizationException) { + throw $denormalizationException; + } + return $value; }