Skip to content

[Serializer] Ability to add custom annotations #38993

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

Open
d42ohpaz opened this issue Nov 4, 2020 · 8 comments
Open

[Serializer] Ability to add custom annotations #38993

d42ohpaz opened this issue Nov 4, 2020 · 8 comments

Comments

@d42ohpaz
Copy link

d42ohpaz commented Nov 4, 2020

Description
Similar how we can add custom validator annotations (https://symfony.com/doc/current/validation/custom_constraint.html), it would be beneficial to be able to create custom serialization annotations to augment existing functionality on a per-property/method basis.

Right now, Groups, SerializedName, and Ignore are all hard-coded into the serialization process via the AttributeMetadaInterface, AnnotationLoader, and the ClassMetadataInterface. There is no easy or intuitive way to create and use custom annotations currently that I have found (If I'm mistaken, I'd love to hear more).

Example
Two use cases:

  1. Encryption: we sometimes serialize personally-identifiable-information (PII) as part of a data transfer process from an API to a consumer endpoint. However, for obvious security reasons, we encrypt this PII so if it is intercepted during transmission then the data is still secure. When calling the serialize process, we have to leak our implementation by designating which fields of our models and entities need to be encrypted (typically in the controller). Instead, it would be nice to write an @Encrypt() annotation that can decorate the properties inside of the entities themselves and automatically encrypt - similar to how @Ignore or @SerializedName works.
  2. Dates: While we can globally set a specific date format for our DateTime instances, there are some circumstances where we need to arbitrarily send back a date in a different format (e.g., just a date or a date with a time or a date/time with timezone information).

Thank you.

@ogizanagi
Copy link
Contributor

ogizanagi commented Nov 8, 2020

Regarding the second use-case with dates, I think a @Serializer\Context() annotation (and xml/yaml mapping equivalent) would do it. You would use it like this:

class Foo
{
    /**
     * @var \DateTime
     *
     * @Serializer\Context({
     *      DateTimeNormalizer::FORMAT_KEY = \DateTime:: RFC3339
     * })
     */
    public $date;
}

The annotation could accept a normalizationContext, denormalizationContext or both context at once (default option), and perhaps a traverse option to forward the context on deeper nodes if any.
Any normalizer with specific options would benefit from it, as it'll allow to configure anything on a per-case basis.

@d42ohpaz
Copy link
Author

d42ohpaz commented Nov 9, 2020

Regarding the second use-case with dates, I think a @Serializer\Context() annotation ... would do it.

To me that still feels like it's leaking the DateTimeNormalizer implementation; or any other context implementation. One of the benefits of custom annotations is that you get to hide your implementation neatly inside the annotation. Then if that implementation needs to change, however much so, you don't have to dig around updating all of your entities.

@ogizanagi
Copy link
Contributor

ogizanagi commented Nov 9, 2020

Sure, it does not aim to solve your custom annotations feature request, which is requiring you to write some custom code.

But it solves part of the described use-case and many others, by providing out-of-the-box a way to configure existing (de)normalizers on a per-case-basis. The context keys of these normalizers are part of their API, so it's not really "leaking implementation"; it provides a flexible way to configure it.

@d42ohpaz
Copy link
Author

d42ohpaz commented Nov 9, 2020

I don't disagree that it would be beneficial to be able to configure context on a per-field basis; I just didn't want my feature request to get lost to this new idea. Do you want me to create a new feature request for the Context annotation? Or would you be okay doing that yourself since it was your idea?

@derrabus
Copy link
Member

derrabus commented Nov 9, 2020

To me that still feels like it's leaking the DateTimeNormalizer implementation; or any other context implementation.

Sure, but you could build a custom annotation on top of that:

#[\Attribute]
class DateFormat extends Context
{
    public function __construct(string $format)
    {
        parent::__construct([
            DateTimeNormalizer::FORMAT_KEY => $format
        ]);
    }
}

@OskarStark
Copy link
Contributor

Regarding the first use case, this would fit well in the new Encryption component by @Nyholm

#39344

@carsonbot
Copy link

Thank you for this suggestion.
There has not been a lot of activity here for a while. Would you still like to see this feature?

@Nyholm
Copy link
Member

Nyholm commented Jul 1, 2021

Please keep this open

@carsonbot carsonbot removed the Stalled label Jul 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants