[Serializer] Fix recursive custom normalizer #19532
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As mentioned in the following issue: symfony/symfony#53708, the example showing how to create a custom normalizer leads to an infinite recursion.
I could have been fixed like that:
class TopicNormalizer implements NormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; + private const ALREADY_CALLED = self::class.'_already_called'; + public function __construct( private UrlGeneratorInterface $router, ) { } public function normalize($topic, string $format = null, array $context = []): array { + $context[self::ALREADY_CALLED] = true; + $data = $this->normalizer->normalize($topic, $format, $context); // Here, add, edit, or delete some data: $data['href']['self'] = $this->router->generate('topic_show', [ 'id' => $topic->getId(), ], UrlGeneratorInterface::ABSOLUTE_URL); return $data; } public function supportsNormalization($data, string $format = null, array $context = []): bool { + if ($context[self::ALREADY_CALLED] ?? false) { + return false; + } + return $data instanceof Topic; } public function getSupportedTypes(?string $format): array { return [ - Topic::class => true, + Topic::class => false, ]; } }But this will prevent the normalizer to be cacheable (because it depends on the context).
Instead, I dropped the use of
NormalizerAwareInterfaceandNormalizerAwareTraitand used an explicit constructor injection instead.WDYT?