Skip to content

[Serializer] deprecated normalizers and encoders who dont implement the base interfaces #27819

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

Merged
merged 1 commit into from
Sep 25, 2018
Merged

[Serializer] deprecated normalizers and encoders who dont implement the base interfaces #27819

merged 1 commit into from
Sep 25, 2018

Conversation

rodnaph
Copy link
Contributor

@rodnaph rodnaph commented Jul 3, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets None
License MIT
Doc PR None

Currently the Serializer can be constructed with any object regardless of whether or not it implements NormalizerInterface or DenormalizerInterface. This object will then be ignored when getting a normalizer/denormalizer, so in effect silently ignored for serializer operations.

This change throws an exception on construct if a given normalizer object does not implement one of these interfaces - are there use cases where this would not be true?

Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jul 3, 2018

Has this been introduced for 4.2? If not, this should throw a deprecation instead I suppose?
Note that the exception should be one line per our CS.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see comment)

@rodnaph
Copy link
Contributor Author

rodnaph commented Jul 3, 2018

@nicolas-grekas Ok I'll switch the exception to a deprecation warning - can you advise which since/to versions this warning should read?

eg. Passing normalizers which don't implement either NormalizerInterface or DenormalizerInterface has been deprecated since X and will throw an exception in Y

@nicolas-grekas
Copy link
Member

LGTM, let's propose this yes.

@rodnaph
Copy link
Contributor Author

rodnaph commented Jul 4, 2018

@nicolas-grekas Switched to deprecation with docs.

@nicolas-grekas nicolas-grekas changed the title Invalid Normalizer Exception [Serializer] Invalid Normalizer Exception Jul 4, 2018
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just some minor comment

UPGRADE-4.2.md Outdated
@@ -64,3 +64,5 @@ Serializer

* Relying on the default value (false) of the "as_collection" option is deprecated since 4.2.
You should set it to false explicitly instead as true will be the default value in 5.0.
* Deprecated creating a `Serializer` with normalizers which do not implement
either `NormalizerInterface` or `DenormalizerInterface`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing indentation

UPGRADE-5.0.md Outdated
----------

* Creating a `Serializer` with normalizers that do not implement either
`NormalizerInterface` or `DenormalizerInterface` will now throw an exception.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing indentation

-----

* deprecated creating a `Serializer` with normalizers which do not implement
either `NormalizerInterface` or `DenormalizerInterface`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation


if (!($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) {
@trigger_error(\sprintf('Passing normalizers (%s) which do not implement either %s or %s has been deprecated since 4.2 and will throw an exception in 5.0', get_class($normalizer), NormalizerInterface::class, DenormalizerInterface::class), E_USER_DEPRECATED);
// throw new \InvalidArgumentException(\sprintf('The class %s does not implement %s or %s', get_class($normalizer), NormalizerInterface::class, DenormalizerInterface::class));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add double quotes around all the "%s"
the " and will throw an exception in 5." part should be removed
and a final dot added

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should have been :)

@rodnaph
Copy link
Contributor Author

rodnaph commented Jul 4, 2018

@nicolas-grekas Done, thanks.

@@ -78,6 +78,11 @@ public function __construct(array $normalizers = array(), array $encoders = arra
if ($normalizer instanceof NormalizerAwareInterface) {
$normalizer->setNormalizer($this);
}

if (!($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) {
@trigger_error(\sprintf('Passing normalizers ("%s") which do not implement either "%s" or "%s" has been deprecated.', get_class($normalizer), NormalizerInterface::class, DenormalizerInterface::class), E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has been deprecated since Symfony 4.2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh :(

@ogizanagi
Copy link
Contributor

Injecting something else than a NormalizerInterface or DenormalizerInterface wouldn't make sense and would be a misuse in the first place. So I don't understand why we should trigger a deprecation here rather than throw the exception directly. It works and is only ignored by luck, as we share the same property for normalizers and denormalizers and use instanceof checks in getNormalizer/getDenormalizer.
If any app is misusing it, this exception would be raised by any test covering part of the app using the serializer and should be fixed right away.

@dunglas
Copy link
Member

dunglas commented Jul 4, 2018

Altenative proposal:

    /**
     * @param NormalizerInterface[]|DenormalizerInterface[] $normalizers
     * @param EncoderInterface[]|DecoderInterface[] $encoders
     */
    public function __construct(array $normalizers = array(), array $encoders = array())

No deprecation, no overhead.

@dunglas
Copy link
Member

dunglas commented Jul 4, 2018

Should be done for encoders too btw.

@nicolas-grekas
Copy link
Member

Good idea to add the docblock @dunglas, let's do that. The instanceof checks are mostly free not sure that's overhead. Don't you want to have an exception in 5.0?
@ogizanagi let's not argue about when we're ok to break BC, we already made the mistake. A deprecation is not the end of the world.

@rodnaph
Copy link
Contributor Author

rodnaph commented Jul 5, 2018

Regards docblock... My reason for adding this check was having lost time debugging a mistake with a normalizer service I was injecting, a runtime exception would have be the quickest notification (docs or static analysis probably wouldn't have highlighted it for me in that instance, but of course worth having).

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jul 5, 2018

Still let's add them also :)

@rodnaph
Copy link
Contributor Author

rodnaph commented Jul 5, 2018

👍

@@ -64,6 +64,10 @@ class Serializer implements SerializerInterface, ContextAwareNormalizerInterface
private $denormalizerCache = array();
private $normalizerCache = array();

/**
* @param NormalizerInterface[]|DenormalizerInterface[] $normalizers
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax we previously used for such arrays is (NormalizerInterface|DenormalizerInterface)[], like in

But as it's still not supported by IDEs AFAIK 👍 to keep as is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current syntax is a bit miss leading as it suggests either array of NormalizerInterface or an array of DenormalizerInterface but not mixed.

@dunglas
Copy link
Member

dunglas commented Sep 5, 2018

Can you rebase please?

@nicolas-grekas nicolas-grekas changed the title [Serializer] Invalid Normalizer Exception [Serializer] deprecated normalizers and encoders who dont implement the base interfaces Sep 21, 2018
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(rebased)

@fabpot
Copy link
Member

fabpot commented Sep 25, 2018

Thank you @rodnaph.

@fabpot fabpot merged commit cbc2be8 into symfony:master Sep 25, 2018
fabpot added a commit that referenced this pull request Sep 25, 2018
…ont implement the base interfaces (rodnaph)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Serializer] deprecated normalizers and encoders who dont implement the base interfaces

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | None
| License       | MIT
| Doc PR        | None

Currently the `Serializer` can be constructed with any object regardless of whether or not it implements `NormalizerInterface` or `DenormalizerInterface`. This object will then be ignored when getting a normalizer/denormalizer, so in effect silently ignored for serializer operations.

This change throws an exception on construct if a given normalizer object does not implement one of these interfaces - are there use cases where this would not be true?

Commits
-------

cbc2be8 [Serializer] deprecated normalizers and encoders who dont implement the base interfaces
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
This was referenced Nov 3, 2018
nicolas-grekas added a commit that referenced this pull request May 29, 2019
…ders passed to Serializer (ogizanagi)

This PR was merged into the 5.0-dev branch.

Discussion
----------

[Serializer] Throw exception on invalid normalizers/encoders passed to Serializer

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | #27819   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A <!-- required for new features -->

As planned in #27819

Commits
-------

5ab6ad4 [Serializer] Throw exception on invalid normalizers/encoders passed to Serializer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants