Skip to content

[Serializer] Add methods getSupportedTypes to allow better performance #18042

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
fabpot opened this issue Mar 10, 2023 · 8 comments
Closed

[Serializer] Add methods getSupportedTypes to allow better performance #18042

fabpot opened this issue Mar 10, 2023 · 8 comments
Labels
hasPR A Pull Request has already been submitted for this issue. Serializer
Milestone

Comments

@fabpot
Copy link
Member

fabpot commented Mar 10, 2023

Q A
Feature PR symfony/symfony#49291
PR author(s) @tucksaun, @nicolas-grekas
Merged in 6.3

We created this issue to not forget to document this new feature. We would really appreciate if you can help us with this task. If you are not sure how to do it, please ask us and we will help you.

To fix this issue, please create a PR against the 6.3 branch in the symfony-docs repository.

Thank you! 😄

@fabpot fabpot added this to the 6.3 milestone Mar 10, 2023
@tucksaun
Copy link
Contributor

@javiereguiluz should this one be added to the list in #17912 ?

@nicolas-grekas
Copy link
Member

When documenting, this should also consider symfony/symfony#49735

@tacman
Copy link
Contributor

tacman commented May 13, 2023

An example? Usually Symfony deprecations make it pretty easy to fix, but there's not even a return type (which needs to be an array).

    public function getSupportedTypes(?string $format)
    {
        return [];
        // TODO: Implement getSupportedTypes() method.
    }

    // delete this removing the 'implements CacheableSupportsMethodInterface'
    public function hasCacheableSupportsMethod(): bool
    {
        return true;
    }

@nicolas-grekas
Copy link
Member

nicolas-grekas commented May 19, 2023

For inspiration:

.. versionadded:: 6.3

    The `getSupportedTypes()` method was introduced in Symfony 6.3.

Both :class:`Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface` and
:class:`Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface` contain a new method `getSupportedTypes()`.
This method allows normalizers or denormalizers to expose their supported types and the associated cacheability to the
Serializer. With this info, even if the `supports*()` call is not cacheable, the Serializer can skip a ton of method calls
to `supports*()` improving performance substantially in some cases.

The `getSupportedTypes()` method should return an array where the keys represent the supported types, and the values
indicate whether the result of the `supports*()` method call can be cached or not. The format of the returned array is as
follows:

- The special key `object` can be used to indicate that the normalizer or denormalizer supports any classes or
  interfaces.
- The special key `*` can be used to indicate that the normalizer or denormalizer might support any types.
- The other keys in the array should correspond to specific types that the normalizer or denormalizer supports.
- The values associated with each type should be a boolean indicating if the result of the `supports*()` method call for
  that type can be cached or not. A value of `true` means that the result is cacheable, while `false` means that the
  result is not cacheable.
- A `null` value for a type means that the normalizer or denormalizer does not support that type.

Here is an example of how to use the `getSupportedTypes()` method:

.. code-block:: php

    use Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface;

    class MyNormalizer implements NormalizerInterface
    {
        // ...

        public function getSupportedTypes(?string $format): array
        {
            return [
                'object' => null, // Doesn't supports any classes or interfaces
                '*' => false, // Supports any other types, but the result is not cacheable
                MyCustomClass::class => true, // Supports MyCustomClass and result is cacheable
            ];
        }
    }

Note that `supports*()` method implementations should not assume that `getSupportedTypes()` has been called before.

@dozer111
Copy link

does it enough to just duplicate the class code like this

public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
    {
        return SomeMyClass::class === $type;
    }

    public function getSupportedTypes(?string $format): array
    {
        return [
            SomeMyClass::class => true
        ];
    }

?

@andrew-demb
Copy link
Contributor

does it enough to just duplicate the class code like this

public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
    {
        return SomeMyClass::class === $type;
    }

    public function getSupportedTypes(?string $format): array
    {
        return [
            SomeMyClass::class => true
        ];
    }

?

Yes

@ro0NL
Copy link
Contributor

ro0NL commented Nov 20, 2024

IIUC a one size fits all implemenation is

    public function getSupportedTypes(?string $format): array
    {
        return ['*' => false];
    }

in case of many complex supports* methods

@FranzBruckner
Copy link

By just reading the new documentation it's very unclear what cacheable means. I tried to find it out by interpreting the code.

The old documentation on the other hand describes that pretty well, so maybe it would be a good idea to add this part to the new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hasPR A Pull Request has already been submitted for this issue. Serializer
Projects
None yet
Development

No branches or pull requests

10 participants