8000 [Serializer] PartialDenormalizationException broken when denormalize array of values · Issue #58281 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sidz opened this issue Sep 16, 2024 · 2 comments
Closed

Comments

@sidz
Copy link
Contributor
sidz commented Sep 16, 2024

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

@sidz sidz added the Bug label Sep 16, 2024
@sidz sidz changed the title [Serializer] PartialDenormalizationException broken on [Serializer] PartialDenormalizationException broken when denormalize array of values Sep 16, 2024
@mtarld
Copy link
Contributor
mtarld commented Sep 18, 2024

Hey @sidz,
Thanks for reporting that!
I think the issue is rather occurring because your property is a variadic parameter.
I created a fix available here: #58306, does it solve your issue?

@sidz
Copy link
Contributor Author
sidz commented Sep 18, 2024

Thank you @mtarld!

Seems like your changes fix this issue.

nicolas-grekas added a commit that referenced this issue Oct 3, 2024
…arams (mtarld)

This PR was merged into the 6.4 branch.

Discussion
----------

[Serializer] Collect denormalization errors for variadic params

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #58281
| License       | MIT

Wrap variadic parameters denormalization in a try/catch to collect denormalization errors.

Commits
-------

cdb2e6e [Serializer] Catch `NotNormalizableValueException` for variadic parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
0