diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index c2b3ebfb3c6c2..082ad5f2bb5d9 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.2 +--- + + * Throw `NotNormalizableValueException` instead of `InvalidArgumentException` in case of invalid data type in `ArrayDenormalizer` + 6.1 --- diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index a212704b7c596..1abfc3a517ed6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Serializer\Normalizer; +use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Exception\BadMethodCallException; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\NotNormalizableValueException; @@ -36,13 +37,14 @@ public function denormalize(mixed $data, string $type, string $format = null, ar if (null === $this->denormalizer) { throw new BadMethodCallException('Please set a denormalizer before calling denormalize()!'); } - if (!\is_array($data)) { - throw new InvalidArgumentException('Data expected to be an array, '.get_debug_type($data).' given.'); - } if (!str_ends_with($type, '[]')) { throw new InvalidArgumentException('Unsupported class: '.$type); } + if (!\is_array($data)) { + throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Data expected to be an array, "%s" given.', get_debug_type($data)), $data, [Type::BUILTIN_TYPE_ARRAY], $context['deserialization_path'] ?? ''); + } + $type = substr($type, 0, -2); $builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null; diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php index 1c708738a1565..cccb57cd53086 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php @@ -18,6 +18,7 @@ use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; /** * @author Jordi Boggiano @@ -36,13 +37,14 @@ interface DenormalizerInterface * * @return mixed * - * @throws BadMethodCallException Occurs when the normalizer is not called in an expected context - * @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported - * @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data - * @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data - * @throws LogicException Occurs when the normalizer is not supposed to denormalize - * @throws RuntimeException Occurs if the class cannot be instantiated - * @throws ExceptionInterface Occurs for all the other cases of errors + * @throws BadMethodCallException Occurs when the normalizer is not called in an expected context + * @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported + * @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data + * @throws NotNormalizableValueException Occurs when the item cannot be hydrated with the given data and the error can be collected + * @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data + * @throws LogicException Occurs when the normalizer is not supposed to denormalize + * @throws RuntimeException Occurs if the class cannot be instantiated + * @throws ExceptionInterface Occurs for all the other cases of errors */ public function denormalize(mixed $data, string $type, string $format = null, array $context = []); diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php index 8b53906c405dc..f2091e07383df 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php @@ -27,6 +27,8 @@ final class Php74Full public array $array; /** @var Php74Full[] */ public array $collection; + /** @var Php74Full[] */ + public array $collection2; public Php74FullWithConstructor $php74FullWithConstructor; public DummyMessageInterface $dummyMessage; /** @var TestFoo[] $nestedArray */ diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index f04c4fbbaf97f..7452024d318f5 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -802,7 +802,8 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet "splFileInfo": null, "uuid": null, "array": null, - "collection": [ + "collection": null, + "collection2": [ { "string": "string" }, @@ -945,12 +946,21 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet 'useMessageForUser' => false, 'message' => 'The type of the "array" attribute for class "Symfony\\Component\\Serializer\\Tests\\Fixtures\\Php74Full" must be one of "array" ("null" given).', ], + [ + 'currentType' => 'null', + 'expectedTypes' => [ + 'array', + ], + 'path' => 'collection', + 'useMessageForUser' => false, + 'message' => 'Data expected to be an array, "null" given.', + ], [ 'currentType' => 'null', 'expectedTypes' => [ 'string', ], - 'path' => 'collection[1].string', + 'path' => 'collection2[1].string', 'useMessageForUser' => false, 'message' => 'The type of the "string" attribute for class "Symfony\Component\Serializer\Tests\Fixtures\Php74Full" must be one of "string" ("null" given).', ],