-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Add a @Mapping Annotation #39048
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
base: 7.4
Are you sure you want to change the base?
[Serializer] Add a @Mapping Annotation #39048
Conversation
Hey! I see that this is your first PR. That is great! Welcome! Symfony has a contribution guide which I suggest you to read. In short:
Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change. When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor! I am going to sit back now and wait for the reviews. Cheers! Carsonbot |
@ro0NL This annotation has not be created to replace per property annotations, but to to fill the lack of possibility to configure properties/method of a trait from the using class. This is possible in yaml, in xml but not yet with annotations (encouraged by the documentation). When you have to deal with this lack in a project with dozen of entities configured with annotations, you can : switch all your configuration to yaml / xml (ouch !), switch ONLY the concerned class to yaml / xml (yuck) or find a hack (a little less yuck) or a solution. I think this feature, as a lower-level API, could help. The "readability" argument in my description has finaly no importance (It's a side-effect which could be a bonus for whose like it).
Currently, how it works : For maxDepth & serializedName: For groups: How it works with this annotation: For maxDepth & serializedName: For groups: So I think it is consistent with existing codebase.
Thanks for your suggestion, I just thinked that the three options should be a developper choice, and equivalent in terms of possibilities. You made me realized this PR description was worst that I thinked (emphasizing minor subjective benefits instead of emphazing technical possibilities additions), thanks for that. |
Add a @mapping annotation applicable to a class to configure the groups, the maxDepth, and the serializedName of a set of attributes. This could be used to ease readability when a class own a lot of attributes and the same groups are applied on a recurring basis. This also ease to configure attributes embedded in the traits used by this class, since you can apply some class-specific groups to them (currently a little bit tricky id you don't use the yaml / xml format). The "ignore" metadata is currently not supported, simply for readability reasons (an @IgnoreAttributes annotation would probably be better) bet could easily implemented. The "maxDepth" parameter on the root of the annotation could also be removed, to avoid unnecessary metadata storage for attributes not using it.
db38013
to
3b5d86f
Compare
You may want to use traits from tierce-party bundle, and serialize its properties. The only way to achieve that via annotations is to get a class annotation. Totally open to any other form of annotation allowing that (maybe decline all existing annotation for class usage ? Isn't it more complex to maintain / compute ?) |
You suggest to redeclare all the wanted properties of the trait in each class using it ? (BTW, according to this snippet, it is nice to discover you have to redeclare all the attributes you want to keep.) Could be a life-saver, but it limits the interest of using the trait. |
You live only once, @ro0NL , you live only once ! More seriously, I updated the description, thank you for your comments which helped make it more relevant. |
Add a @mapping annotation applicable to a class to configure the groups, the maxDepth, and the serializedName of a set of attributes.
It allows you to configure the serialization of attributes from traits, when specific to each class, or when the trait comes from a third party library (or from an hexagone of your code you don't want to depend on the serializer)
The "ignore" metadata is currently not supported, simply for readability reasons (an @IgnoreAttributes annotation would probably be better) but could easily implemented.
The "maxDepth" parameter on the root of the annotation could also be removed, to avoid unnecessary metadata storage for attributes not using it.
This annotation also allows you to configure the class attributes at the same place, even if yaml or xml would be a better choice for that in a fresh project.
Let me know if there is any chance this feature to be merged, so I will start working on the documentation.
Note : the fabbot does not accept the php8 attribute, is it too soon for that ?
Main use case example
Let say you want to use a vendor trait, or a very common behavior trait from your application. Sometimes you want some properties to be serialized, sometimes not. Here an example with BlameableEntity from Gedmo DoctrineExtension (you probably want to write your own trait, it just illustrates the confidentiality need):
For a BlogPost, you may want expose thoses properties
For an AnonymousSuggestion, you probably don't want to leak those informations:
For a DisruptiveIdeaDraft, you may want to expose updatedBy, but createdBy only for the managers (because in a first time, you want your team not to be influenced by who created the thing)
or
How it works
Full usage example to configure groups :
you can configure maxDepth generally, or per attribute :
you can specify a serializedName per attribute :
Annotations priorities
Currently, how it works :
For maxDepth & serializedName:
method annotation > property annotation > method annotation from parent class > property annotation from parent class > method annotation from interfaces
For groups:
groups from any annotation are cumulated, not replaced
How it works with this annotation:
For maxDepth & serializedName:
method annotation > property annotation > class annotation (attribute specific) > class annotation (root parameter for maxDepth) > method annotation from parent class > property annotation from parent class > class annotation from parent class (attribute specific) > class annotation from parent class (root parameter for maxDepth) > method annotation from interface > class annotation from interface (attribute specific) > class annotation from interface (root parameter for maxDepth)
NOTE : looks complicated, but it's the same logic sequence
For groups:
groups from any annotation are cumulated, not replaced