-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Add normalizer / denormalizer awarness #17545
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
ping @dunglas |
Why not just creating two separate classes? A normalizer class and a denormalizer class? It will be easier and respectful of SOLID principles. |
Forget my previous comment, I need to dive deeper into this PR. |
Hum actually your comment makes me wonder if we could provides the 3 implementations as a Trait instead of an abstract class, so we would have better composition, WDYT ? |
@@ -11,7 +11,12 @@ | |||
|
|||
namespace Symfony\Component\Serializer\Tests; | |||
|
|||
use Prophecy\Argument; |
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.
Sadly (IMO) we don't use Prophecy in Symfony.
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.
Not allowed ? Or phpunit version can be too small for it ?
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.
Not allowed for consistency. We still use the old mock system.
I don't understand why this is not doable with the current system? Can you be more precise about the use case? Isn't tests like this one https://github.com/dunglas/DunglasApiBundle/blob/1.x/JsonLd/Serializer/ItemNormalizer.php#L102-L104 enough? |
Use case is for recursivity like #17193, IMO SerializerAwareInterface does not make sense in the SerializerAwareNormalizer (interface make sense, but not the abstract class, unless you went to double encode / decode something, but never seen it). This is mainly to avoid the check of a NormalizerInterface / DenormalizerInterface each time and for each class, Another way to do this would be to transform the SerializerAwareNormalizer to depend on the Serializer Class (not the interface). |
IMO it introduces a lot of complexity (with crossed circular references) and can be hard to debug (what if the user sets different objects in $normalizer, $serializer and $denormalizer) for no real gain. As the default |
Having the check of NormalizerInterface / DenormalizerInterface over a class which is expected to be a SerializerInterface feel hackish IMO What about having a trait for each of the 3 aware interface and deprecate the SerializerAwareNormalizer ? |
Also having the check on the current SerializerAwareNormalizer force users to use the Serializer class (or anything implementing the SerializerInterface), having this would better decouple the Normalizer part from the Serializer. |
👍 for the traits. They can solve some issues in API Platform too. |
e6905cd
to
53cf61c
Compare
Done with traits and deprecated the SerializerAwareNormalizer |
use Symfony\Component\Serializer\SerializerAwareInterface; | ||
|
||
/** | ||
* SerializerAware Normalizer implementation. | ||
* | ||
* @author Jordi Boggiano <[email protected]> | ||
* | ||
* @deprecated since version 3.1, to be removed in 4.0. Use the SerializerAwareTrait instead. |
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.
You must trigger a deprecation error like this one: @trigger_error(sprintf('The class "%s" is deprecated. It will be removed in Symfony 4.0. Use the "Symfony\Component\Serializer\SerializerAwareTrait" trait instead.', __CLASS__), E_USER_DEPRECATED);
You should also adapt existing normalizers in Symfony to avoid using this deprecated class. But if you do that... It will be a small BC break (ObjectNormalizer
will not inherit from the SerializerAwareNormalizer
type anymore - but as there is a corresponding interface, the BC break should be very limited). What do you think @symfony/deciders?
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.
You must trigger a deprecation error
Since there is no more code / method in this class i don't think it's possible, i have done this deprecated feature in the same way it was done for the ContainerAwareTrait in 2.8 https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/DependencyInjection/ContainerAware.php
You should also adapt existing normalizers in Symfony to avoid using this deprecated class
It's already done, but maybe i have miss some implementations ?
👍 ping @symfony/deciders |
53cf61c
to
790fb6e
Compare
rebased |
Thanks @joelwurtz for working on this feature, this is much appreciated. |
…oelwurtz) This PR was merged into the 3.1-dev branch. Discussion ---------- [Serializer] Add normalizer / denormalizer awarness | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | SerializerAwareInterface is not really usable in a decode -> normalize context, as if we need to transform a subproperty with another class, we only have the context of a serialize however the data is already decoded so it will fail. This interfaces allow a normalizer / denormalizer to have a sub normalization / denormalization process context and not the whole context with serializer. I have also add a `AwareNormalizer` which is an abstract class implementing the 3 aware interfaces like it was done with the SerializerAwareNormalizer, since it's a standard way to implement this interfaces. This is needed for #17516, other solution would be to have a RawDecoder which don't decode and return the input as it is, but really not a fan of this solution. Commits ------- 790fb6e Add normalizer / denormalizer awarness
@joelwurtz what happened to the |
It was removed in favor of having 3 traits, one for each possiblity |
|
||
/** | ||
* Normalizer implementation. | ||
* | ||
* @author Kévin Dunglas <[email protected]> | ||
*/ | ||
abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface | ||
abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface |
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 is a BC break for anyone having a type hint on the SerializerAwareNormalizer
class.
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.
Should we readd the extends and override the methods ? Or is this an acceptable BC break ?
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.
So according to this : http://symfony.com/doc/current/contributing/code/bc.html#id10 it is not something acceptable, will do a PR to readd this class
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.
Yeah, sorry I was on a mobile when writing the comment and forgot to add a reference to that later.
* | ||
* @param NormalizerInterface $normalizer A NormalizerInterface instance | ||
*/ | ||
public function setSerializer(NormalizerInterface $normalizer) |
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.
setNormalizer
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.
See #18536
…ace (joelwurtz) This PR was merged into the 3.1-dev branch. Discussion ---------- Fix the wrong method name given the corresponding interface | Q | A | ------------- | --- | Branch? | "master" | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17545 Follow up | License | MIT | Doc PR | This a follow up of #17545 as i introduce bad methods name in the traits sorry :/  Commits ------- 231819e Fix the wrong method name given the corresponding interface
This PR was merged into the 3.1-dev branch. Discussion ---------- [Serializer] fix parent class of AbstractNormalizer | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17545 (comment) | License | MIT | Doc PR | We must maintain the parent class to not break BC. Commits ------- 45b9ed9 fix parent class of AbstractNormalizer
This PR was merged into the 3.1-dev branch. Discussion ---------- [Serializer] fix parent class of AbstractNormalizer | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony/symfony#17545 (comment) | License | MIT | Doc PR | We must maintain the parent class to not break BC. Commits ------- 45b9ed9 fix parent class of AbstractNormalizer
SerializerAwareInterface is not really usable in a decode -> normalize context, as if we need to transform a subproperty with another class, we only have the context of a serialize however the data is already decoded so it will fail.
This interfaces allow a normalizer / denormalizer to have a sub normalization / denormalization process context and not the whole context with serializer.
I have also add a
AwareNormalizer
which is an abstract class implementing the 3 aware interfaces like it was done with the SerializerAwareNormalizer, since it's a standard way to implement this interfaces.This is needed for #17516, other solution would be to have a RawDecoder which don't decode and return the input as it is, but really not a fan of this solution.