Skip to content

fix(symfony): keep denormalize on decorated normalizers - #8606

Merged
soyuka merged 3 commits into
api-platform:4.4from
soyuka:fix/item-normalizer-decoration-bc-8550
Sep 29, 2026
Merged

soyuka merged 3 commits into
api-platform:4.4from
soyuka:fix/item-normalizer-decoration-bc-8550

Conversation

@soyuka

@soyuka soyuka commented Sep 29, 2026

Copy link
Copy Markdown
Member
Q A
Branch? 4.4
Tickets Fixes #8550
License MIT

#7713 split each item normalizer into a normalizer and an ItemDenormalizer registered one priority higher (for example api_platform.jsonld.denormalizer.item at -889, api_platform.jsonld.normalizer.item at -890). The documentation told users to add custom denormalization logic by decorating the normalizer. After the split, such a decorator is never reached for denormalization, and nothing warns about it.

This adds a BC layer. ItemNormalizerDecorationBcPass looks for user decorators of api_platform.{serializer,jsonld,jsonapi,graphql}.normalizer.item that implement DenormalizerInterface. When it finds one, it removes the serializer.normalizer tag from the matching *.denormalizer.item service, so denormalization goes through the decorated normalizer again, which is the pre-4.4 behaviour. It also triggers a deprecation that asks users to decorate the denormalizer service instead. Our own decorators (api_platform.* ids, for example Elasticsearch) are ignored, and so are apps that already decorate the denormalizer.

The pass stays on 5.0 and main, and goes away in 6.0 together with the deprecated ItemNormalizer::denormalize().

Tests:

  • ItemNormalizerDecorationBcPassTest: the tag is removed and the deprecation is triggered; a normalize-only decorator, a decorator that already targets the denormalizer, and an api_platform.* decorator change nothing.
  • DecoratedItemNormalizerDenormalizationTest: a POST through an #[AsDecorator] decorator of the JSON-LD normalizer, with its own kernel. It fails before this change with Expected 'decorated', Actual 'original'.

Since api-platform#7713 each item normalizer has a dedicated denormalizer registered one priority higher, so a user decorator of the normalizer that also implements DenormalizerInterface was never reached for denormalization. When such a decorator exists, detach the matching denormalizer from the serializer chain and trigger a deprecation pointing to the denormalizer service.

Fixes api-platform#8550
In the full suite, earlier kernel boots leave Symfony ErrorHandler registered, which swallows the deprecation before expectUserDeprecationMessage sees it. Capture it with a local error handler, as AttributeFilterPassTest does.
@soyuka
soyuka merged commit e727149 into api-platform:4.4 Sep 29, 2026
115 of 117 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant