feat: pass #[Context] attribute data to property describers#2722
feat: pass #[Context] attribute data to property describers#2722lacatoire wants to merge 2 commits intonelmio:5.xfrom
Conversation
Read per-property normalization context from Symfony's #[Context] serializer attribute and merge it with the model's serialization context before passing it to property/type describers. This enables custom model describers to react to context set via #[Context] on properties. For instance, the built-in EnumModelDescriber already supports a FORCE_NAMES context key that switches enum output from backed values to case names — this now works when set via the attribute. Fixes nelmio#2402
There was a problem hiding this comment.
Pull request overview
This PR adds support for Symfony Serializer’s #[Context] attribute on individual properties so that per-property normalization context is merged into the serialization context passed to property/type describers during OpenAPI schema generation (addressing #2402).
Changes:
- Extend
ObjectModelDescriberto read per-property serializer metadata and merge#[Context]normalization context into the context used for describing each property. - Update the internal
describeProperty()flow to accept a per-property context and pass it to the property/type describer. - Add a functional test (controller + entity + JSON fixture) proving that enum schema generation changes when
EnumModelDescriber::FORCE_NAMESis set via#[Context].
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/ModelDescriber/ObjectModelDescriber.php |
Merges per-property #[Context] normalization context into the context passed to describers. |
tests/Functional/ControllerTest.php |
Adds a functional test case enabling Serializer attributes and exercising the new behavior. |
tests/Functional/Controller/ContextAttributeController.php |
New endpoint fixture to generate a schema for an entity using per-property #[Context]. |
tests/Functional/Entity/EntityWithContext.php |
Defines an entity with an enum property annotated with #[Context] to force enum name output. |
tests/Functional/Fixtures/ContextAttributeController.json |
Expected OpenAPI output showing two enum schemas (values vs names) based on per-property context. |
| private function describeProperty(array|Type $types, Model $model, OA\Schema $property, string $propertyName, array $propertyContext = []): void | ||
| { | ||
| $context = [] !== $propertyContext ? $propertyContext : $model->getSerializationContext(); | ||
|
|
There was a problem hiding this comment.
describeProperty() treats an explicitly provided empty $propertyContext as “not provided” due to $context = $propertyContext ?: $model->getSerializationContext();. This makes it impossible to intentionally override the model context with an empty context and also doesn’t match the docblock wording (“used instead of the model-level context when provided”). Consider changing the parameter to ?array $propertyContext = null and using ?? to distinguish null from an intentionally empty array (or remove the default and always pass a context).
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 5.x #2722 +/- ##
==========================================
+ Coverage 95.68% 95.69% +0.01%
==========================================
Files 94 94
Lines 3079 3088 +9
==========================================
+ Hits 2946 2955 +9
Misses 133 133 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
Read per-property normalization context from Symfony's
#[Context]serializer attribute and merge it into the serialization context before passing it to property/type describers.Previously, the
#[Context]attribute on properties was completely ignored when generating OpenAPI schemas. This meant that custom context keys (likeEnumModelDescriber::FORCE_NAMES) had no effect when set via the attribute.How it works
In
ObjectModelDescriber::describe(), theClassMetadataFactory(already injected for discriminator mapping) now also providesgetAttributesMetadata(). For each property, the normalization context from#[Context]is merged with the model's base serialization context and passed to describers.Example
Changes
ObjectModelDescriber: extractattributesMetadataalongside discriminator mapping; for each property, merge#[Context]normalization context into the per-property context passed todescribeProperty()describeProperty(): accept optional$propertyContextparameter, used instead of the model-level context when providedEntityWithContextentity with#[Context]on an enum property,ContextAttributeController, and auto-generated fixture proving enum names are usedFixes #2402