Skip to content

[Serializer] Fix TemplateType handling in AbstractObjectNormalizer #58033

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
wants to merge 1 commit into from

Conversation

valtzu
Copy link
Contributor

@valtzu valtzu commented Aug 18, 2024

Q A
Branch? 7.1
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #58031
License MIT

TypeInfo component introduced in 7.1 causes AbstractObjectNormalizer to throw an error when you have /** @var T */ in your DTO – see the related issue for details.

@valtzu valtzu requested a review from dunglas as a code owner August 18, 2024 21:02
@carsonbot carsonbot added this to the 7.1 milestone Aug 18, 2024
@valtzu valtzu force-pushed the serializer-generics-template-fix branch from d0a7bf5 to 2ffa135 Compare August 18, 2024 21:06
@chalasr
Copy link
Member

chalasr commented Aug 19, 2024

/cc @mtarld

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the file should be renamed back to AbstractObjectNormalizerTest

@xabbuh
Copy link
Member

xabbuh commented Aug 20, 2024

According to #58031 (comment) this used to work in 7.0. However if I rebase your changes on the 7.0 branch it fails like this:

There was 1 error:

1) Symfony\Component\Serializer\Tests\Normalizer\AbstractObjectNormalizerTest::testDenormalizeGenerics
Symfony\Component\Serializer\Exception\NotNormalizableValueException: The type of the "value" attribute for class "Symfony\Component\Serializer\Tests\Normalizer\DummyGenericsValueWrapper" must be one of "Symfony\Component\Serializer\Tests\Normalizer\T" ("array" given).

@valtzu valtzu force-pushed the serializer-generics-template-fix branch from 2ffa135 to 8eb5dc4 Compare August 20, 2024 16:11
@valtzu
Copy link
Contributor Author

valtzu commented Aug 20, 2024

According to #58031 (comment) this used to work in 7.0. However if I rebase your changes on the 7.0 branch it fails like this:

There was 1 error:

1) Symfony\Component\Serializer\Tests\Normalizer\AbstractObjectNormalizerTest::testDenormalizeGenerics
Symfony\Component\Serializer\Exception\NotNormalizableValueException: The type of the "value" attribute for class "Symfony\Component\Serializer\Tests\Normalizer\DummyGenericsValueWrapper" must be one of "Symfony\Component\Serializer\Tests\Normalizer\T" ("array" given).

It worked because in the example in the issue there is a custom denormalizer which denormalizes the input before passing it to the object denormalizer. I'm aware that it is not how you should call denormalizer, but on the other hand, it did work in previous versions.

The same would be

$normalizer->denormalize(['value' => new DummyGenericsValue()], DummyGenericsValueWrapper::class)

and this does work on top of 7.0.

I did add a test for this case too but I'm not sure if this type of misuse should be supported? Or is my assumption about "you should only pass arrays/scalars to denormalize" wrong 🤔

@@ -665,6 +665,8 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
if ($t instanceof CollectionType) {
$collectionKeyType = $t->getCollectionKeyType();
$collectionValueType = $t->getCollectionValueType();
} elseif ($t instanceof Type\TemplateType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add a proper use instead to be consistent

@@ -665,6 +665,8 @@ private function validateAndDenormalize(Type $type, string $currentClass, string
if ($t instanceof CollectionType) {
$collectionKeyType = $t->getCollectionKeyType();
$collectionValueType = $t->getCollectionValueType();
} elseif ($t instanceof Type\TemplateType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That condition must IMO go under the first if of the foreach (L663).
Otherwise, a template of collection won't be handled properly.

Copy link
Contributor Author

@valtzu valtzu Aug 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to handle collections (i.e. T[]) properly this has to be done inside the if ($t instanceof CollectionType) block too

                if ($collectionValueType instanceof TemplateType) {
                    $collectionValueType = $collectionValueType->getBound();
                }

(maybe same should be for $collectionValueKey too)

I wonder would it make more sense to make TemplateType::getBaseType() return $this->getBound() instead of throwing – then we didn't need any of this here. I'm not too familiar with the new TypeInfo component so this could be a silly proposal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder would it make more sense to make TemplateType::getBaseType() return $this->getBound() instead of throwing – then we didn't need any of this here. I'm not too familiar with the new TypeInfo component so this could be a silly proposal.

I indeed think that the bound type should be considered as the base type. Could you please send a PR in that way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, here

@fabpot
Copy link
Member

fabpot commented Sep 18, 2024

Closing in favor of #58259

@fabpot fabpot closed this Sep 18, 2024
fabpot added a commit that referenced this pull request Sep 18, 2024
…` (valtzu)

This PR was merged into the 7.1 branch.

Discussion
----------

[TypeInfo] Return bound type as base type in `TemplateType`

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

This supersedes #58033 as simpler approach.

Commits
-------

f897a7b Fix `TemplateType` handling in `AbstractObjectNormalizer`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants