Skip to content

[Serializer] PartialDenormalizationException broken when denormalize array of values #58281

Closed
@sidz

Description

@sidz

Symfony version(s) affected

6.4

Description

PartialDenormalizationException should be thrown in case collect_denormalization_errors equal to true.

But this is not true for the case when we're trying to denormalize array of values (for example UUIDs but it works for any case)

It happens as DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS is removed on the first iteration, see

if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) {
unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]);
$context['not_normalizable_value_exceptions'] = [];
$errors = &$context['not_normalizable_value_exceptions'];
$denormalized = $normalizer->denormalize($data, $type, $format, $context);
if ($errors) {
// merge errors so that one path has only one error
$uniqueErrors = [];
foreach ($errors as $error) {
if (null === $error->getPath()) {
$uniqueErrors[] = $error;
continue;
}
$uniqueErrors[$error->getPath()] = $uniqueErrors[$error->getPath()] ?? $error;
}
throw new PartialDenormalizationException($denormalized, array_values($uniqueErrors));
}
return $denormalized;
}

I didn't check on earlier versions maybe it has never worked like I expect.

How to reproduce

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Uid\Uuid;

class Test
{
    public array $uids;

    public function __construct(Uuid ...$uids)
    {
        $this->uids = $uids;
    }
}

$normalizers = [new UidNormalizer(), new ObjectNormalizer()];

$serializer = new Serializer($normalizers, [new JsonEncoder()]);

try {
    $dto = $serializer->denormalize(
        ['uids' => [Uuid::v7()->toRfc4122(), '2024-01-15']],
        Test::class,
        'json',
        [AbstractNormalizer::COLLECT_DENORMALIZATION_ERRORS => true]
    );
} catch (PartialDenormalizationException $e) {
    var_dump($e);

    exit;
}

var_dump($dto);

Serializer will throw NotNormalizableValueException instead of PartialDenormalizationException and break collecting the normalization errors.

PHP Fatal error:  Uncaught Symfony\Component\Serializer\Exception\NotNormalizableValueException: The data is not a valid "Symfony\Component\Uid\Uuid" string representation. in /home/projects/symfony-serializer/vendor/symfony/serializer/Exception/NotNormalizableValueException.php:32
Stack trace:
#0 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/UidNormalizer.php(81): Symfony\Component\Serializer\Exception\NotNormalizableValueException::createForUnexpectedDataType()
#1 /home/projects/symfony-serializer/vendor/symfony/serializer/Serializer.php(247): Symfony\Component\Serializer\Normalizer\UidNormalizer->denormalize()
#2 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php(480): Symfony\Component\Serializer\Serializer->denormalize()
#3 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php(647): Symfony\Component\Serializer\Normalizer\AbstractNormalizer->denormalizeParameter()
#4 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php(361): Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalizeParameter()
#5 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php(243): Symfony\Component\Serializer\Normalizer\AbstractNormalizer->instantiateObject()
#6 /home/projects/symfony-serializer/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php(349): Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->instantiateObject()
#7 /home/projects/symfony-serializer/vendor/symfony/serializer/Serializer.php(227): Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->denormalize()
#8 /home/projects/symfony-serializer/index.php(34): Symfony\Component\Serializer\Serializer->denormalize()
#9 {main}
  thrown in /home/projects/symfony-serializer/vendor/symfony/serializer/Exception/NotNormalizableValueException.php on line 32

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions