-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Allow to provide (de)normalization context in mapping #39399
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
Conversation
I haven't reviewed the code yet but I like the idea! Could we also allow to set this annotation on classes? In this case, the context will be applied to the class and all its properties. |
public $normalizationContexts = []; | ||
|
||
/** | ||
* @var array[] Denormalization contexts per group name ("*" applies to all groups) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using *
should be fine since #33540 already relies on this. So no one should name their groups *
.
Otherwise, previous version used an empty string, but we could simply opt for a distinct defaultDenormalizationContext
property as well.
Indeed, I also had this case in mind. I'd say let's polish this one first and iterate over. I don't think it would bring any compatibility issue (anyway we have time until 5.3 release). Note that applying a context on an object property should already do it right now. But we miss a way to add it on class-level, for the root object for instance. |
...Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd
Outdated
Show resolved
Hide resolved
...Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
Outdated
Show resolved
Hide resolved
…ces (ogizanagi) This PR was merged into the 4.4 branch. Discussion ---------- Normalize exceptions messages containing methods references | Q | A | ------------- | --- | Branch? | 4.4 <!-- see below --> | Bug fix? | no | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix symfony/symfony#39399 (comment) <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT | Doc PR | N/A Normalizes across the codebase any exception message mentioning methods to contain a trailing `()` (Seems OK on 5.1 and 5.2 branch after this on is merged up) Commits ------- e2da2acd6d Normalize exceptions messages containing methods references
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com> | ||
*/ | ||
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] | ||
class Context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class Context | |
final class Context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. But we can imagine some legit use-cases for extending it. See #38993 (comment) for instance.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feature could come in handy in my current project.
Thank you @ogizanagi. |
… context in mapping (ogizanagi) This PR was squashed before being merged into the 5.3-dev branch. Discussion ---------- [Serializer] Allow to provide (de)normalization context in mapping | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix symfony#39039 <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT | Doc PR | TODO <!-- required for new features --> As explained in the linked feature request, this brings the ability to configure context on a per-property basis, using Serializer mapping. Considering: ```php use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; class Foo { /** * @Serializer\Context({ DateTimeNormalizer::FORMAT_KEY = 'Y-m-d' }) */ public \DateTime $date; public \DateTime $anotherDate; } ``` `$date` will be formatted with a specific format, while `$anotherDate` will use the default configured one (or the one provided in the context while calling `->serialize()` / `->normalize()`). It can also differentiate normalization and denormalization contexts: ```php use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; class Foo { /** * @Serializer\Context( * normalizationContext = { DateTimeNormalizer::FORMAT_KEY = 'Y-m-d' }, * denormalizationContext = { DateTimeNormalizer::FORMAT_KEY = \DateTime::COOKIE }, * ) */ public \DateTime $date; } ``` As well as act differently depending on groups: ```php use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; class Foo { /** * @Serializer\Groups({ "extended" }) * @Serializer\Context({ DateTimeNormalizer::FORMAT_KEY = \DateTime::RFC3339 }) * @Serializer\Context( * context = { DateTimeNormalizer::FORMAT_KEY = \DateTime::RFC3339_EXTENDED }, * groups = {"extended"}, * ) */ public \DateTime $date; } ``` The annotation can be repeated as much as you want to handle the different cases. Context without groups is always applied first, then context for groups are merged in the provided order. Context provided when calling `->serialize()` / `->normalize()` acts as the defaults for the properties without context provided in the metadata. XML mapping (see tests) is a lot verbose due to the required structure to handle groups. Such metadata contexts are also forwarded to name converters, max depth handlers, callbacks, ... Of course, PHP 8 attributes are also supported: ```php use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; class Foo { #[Serializer\Groups(["extended"])] #[Serializer\Context([DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339])] #[Serializer\Context( context: [DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339_EXTENDED], groups: ["extended"], )] public \DateTime $date; } ``` The PR should be ready for first batch of reviews / discussions. - [x] Make Fabbot happy in 5.2 - [x] Missing `@Context` unit tests - [x] rework xml & phpize values - [x] Fix lowest build issue with annotations => bumped doctrine annotations to 1.7, as for other components Commits ------- 7229fa1 [Serializer] Allow to provide (de)normalization context in mapping
As explained in the linked feature request, this brings the ability to configure context on a per-property basis, using Serializer mapping.
Considering:
$date
will be formatted with a specific format, while$anotherDate
will use the default configured one (or the one provided in the context while calling->serialize()
/->normalize()
).It can also differentiate normalization and denormalization contexts:
As well as act differently depending on groups:
The annotation can be repeated as much as you want to handle the different cases.
Context without groups is always applied first, then context for groups are merged in the provided order.
Context provided when calling
->serialize()
/->normalize()
acts as the defaults for the properties without context provided in the metadata.XML mapping (see tests) is a lot verbose due to the required structure to handle groups.
Such metadata contexts are also forwarded to name converters, max depth handlers, callbacks, ...
Of course, PHP 8 attributes are also supported:
The PR should be ready for first batch of reviews / discussions.
@Context
unit tests