Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Serializer] Introduce named serializers#56823

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fabpot merged 1 commit intosymfony:7.2fromHypeMC:named-serializers
Sep 19, 2024

Conversation

HypeMC
Copy link
Member

@HypeMCHypeMC commentedMay 20, 2024
edited
Loading

QA
Branch?7.2
Bug fix?no
New feature?yes
Deprecations?no
Issues-
LicenseMIT

The idea behind this PR is to allow configuring multiple serializer instances with different default contexts, name converters, and sets of normalizers and encoders. This is useful when your application is communicating with multiple APIs, each with different rules. Similar ideas have been mentionedbefore.

serializer:named_serializers:api1:name_converter:'serializer.name_converter.camel_case_to_snake_case'default_context:enable_max_depth:trueapi2:default_context:enable_max_depth:false

The different serializers can be injected using named aliases:

#[AsController]class HomeController{    #[Route('/', name:'app_home')]publicfunctionindex(SerializerInterface$serializer,// Default serializerSerializerInterface$api1Serializer,// api1 serializer        #[Target('api2.serializer')]// api2 serializerSerializerInterface$someName,    ) {// ...    }}

Multiple normalizer/encoder instances with different arguments are created as child services of the default ones.I also ensured that the same normalizer/encoder instances are reused between different serializers that have the same default context and name converter to minimize the number of child services created.

Custom normalizers/encoders can target specific serializers using theserializer tag attribute:

get_set_method_normalizer:class:Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizerautoconfigure:false# This is needed so that it's not included in the default serializertags:# single serializer        -serializer.normalizer:{ serializer: 'api1' }# or multiple ones        -serializer.normalizer:{ serializer: [ 'api1', 'api2' ] }# use * to include the service in all serializers including the default one        -serializer.normalizer:{ serializer: '*' }

For BC reasons, not setting theserializer tag attribute is the same as setting it to the default one:

tags:        -serializer.normalizer# same as        -serializer.normalizer:{ serializer: 'default' }

The profiler has been updated to support multiple serializer instances:

image

All normalizers/encoders are tagged with additional named serializer specific tags to help with debugging. To get the priority of normalizers/encoders for a certain serializer, use theserializer.normalizer.<name> orserializer.encoder.<name> tags:

$ bin/console debug:container --tag serializer.normalizer.defaultSymfony Container Services Tagged with"serializer.normalizer.default" Tag========================================================================== ------------------------------------------------- ---------- -------------------------------------------------------------------------------------------   Service ID                                        priority   Class name                                                                                  ------------------------------------------------- ---------- -------------------------------------------------------------------------------------------   serializer.denormalizer.unwrapping                1000       Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer                               serializer.normalizer.flatten_exception           -880       Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer    ...  serializer.denormalizer.array                     -990       Symfony\Component\Serializer\Normalizer\ArrayDenormalizer                                    serializer.normalizer.object                      -1000      Symfony\Component\Serializer\Normalizer\ObjectNormalizer                                    ------------------------------------------------- ---------- ------------------------------------------------------------------------------------------- $ bin/console debug:container --tag serializer.normalizer.api1Symfony Container Services Tagged with"serializer.normalizer.api1" Tag======================================================================= ------------------------------------------------- ---------- -------------------------------------------------------------------------------------------   Service ID                                        priority   Class name                                                                                  ------------------------------------------------- ---------- -------------------------------------------------------------------------------------------   serializer.denormalizer.unwrapping                1000       Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer                               get_set_method_normalizer                                    Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer                               serializer.normalizer.flatten_exception           -880       Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer    ...  serializer.denormalizer.array                     -990       Symfony\Component\Serializer\Normalizer\ArrayDenormalizer                                    serializer.normalizer.object                      -1000      Symfony\Component\Serializer\Normalizer\ObjectNormalizer                                    ------------------------------------------------- ---------- ------------------------------------------------------------------------------------------- $ bin/console debug:container --tag serializer.normalizerSymfony Container Services Tagged with"serializer.normalizer" Tag================================================================== ------------------------------------------------- ---------- ---------- ----------------- -------------------------------------------------------------------------------------------   Service ID                                        standard   priority   serializer        Class name                                                                                  ------------------------------------------------- ---------- ---------- ----------------- -------------------------------------------------------------------------------------------   serializer.denormalizer.unwrapping                1          1000                         Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer                               get_set_method_normalizer                                               ["api1","api2"]   Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer                               serializer.normalizer.flatten_exception           1          -880                         Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer    ...  serializer.denormalizer.array                     1          -990                         Symfony\Component\Serializer\Normalizer\ArrayDenormalizer                                    serializer.normalizer.object                      1          -1000                        Symfony\Component\Serializer\Normalizer\ObjectNormalizer                                    ------------------------------------------------- ---------- ---------- ----------------- -------------------------------------------------------------------------------------------

Since Symfony comes with some pre-registered normalizers and encoders, I added options to exclude those in case someone wants to use only custom ones:

serializer:named_serializers:api1:include_built_in_normalizers:falseinclude_built_in_encoders:truename_converter:'serializer.name_converter.camel_case_to_snake_case'default_context:enable_max_depth:true

TBH, I have doubts about the usefulness of this, please let me know your thoughts.

I've split the PR into two commits to ease reviewing:

  • the first commit only rearranges theSerializerPass without adding any features
  • the second commit implements the feature

alamirault, jdreesen, ddegasperi, andrew-demb, yblatti, mtarld, joelwurtz, bastnic, lyrixx, yceruto, and 9 more reacted with thumbs up emojinikophil, dunglas, bastnic, lyrixx, Jibbarth, ging-dev, welcoMattic, and Vorta reacted with heart emoji
@carsonbot

This comment has been minimized.

@carsonbotcarsonbot added this to the7.1 milestoneMay 20, 2024
@HypeMCHypeMCforce-pushed thenamed-serializers branch 2 times, most recently fromecd355d to63409d5CompareMay 20, 2024 11:52
@OskarStarkOskarStark modified the milestones:7.1,7.2May 20, 2024
@alamiraultalamirault mentioned this pull requestMay 20, 2024
fabpot added a commit that referenced this pull requestMay 21, 2024
This PR was merged into the 7.1 branch.Discussion----------Fix singular phpdoc| Q             | A| ------------- | ---| Branch?       | 7.1| Bug fix?      | no| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->| Issues        | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead -->| License       | MIT(Found while reviewing#56823)Commits-------e0f6258 Fix singular phpdoc
@HypeMCHypeMCforce-pushed thenamed-serializers branch 3 times, most recently from3e3ef44 tof1c17d7CompareAugust 12, 2024 19:27
@dunglas
Copy link
Member

Good work! This will help improve performance and reduce the complexity of projects needing multiple serializers to deal with different contexts (ex: serializing data exposed through a public API and deserializing data coming from a third-party service). I'm +1 to merge this.

autoconfigure: false # This is needed so that it's not included in the default serializer

Maybe could we tweak the autoconfigurator to automatically exclude definitions already having an explicitserializer tag? This will improve the DX a bit.

Copy link
Contributor

@mtarldmtarld left a comment

Choose a reason for hiding this comment

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

That's a really great addition!

Just a quick question, why mixing upstandard anddefault as name describing default stuff? Shouldn't we stick todefault only?

fabpot added a commit that referenced this pull requestAug 14, 2024
…hild()` shortcut method (HypeMC)This PR was merged into the 7.2 branch.Discussion----------[DependencyInjection] Add `ContainerBuilder::registerChild()` shortcut method| Q             | A| ------------- | ---| Branch?       | 7.2| Bug fix?      | no| New feature?  | yes| Deprecations? | no| Issues        | -| License       | MITExtracted from#56823 as suggested in#56823 (comment)Commits-------7ba430c [DependencyInjection] Add `ContainerBuilder::registerChild()` shortcut method
@stof
Copy link
Member

Reusing the same normalizer instances is a very bad idea as it would break for any normalizer implementing any of the*Aware interfaces of the component (as instantiating the second serializer would replace the instance that those shared normalizers are aware of)

dunglas, chalasr, mtarld, and jvasseur reacted with thumbs up emoji

@HypeMC
Copy link
MemberAuthor

Rebase needed after#58013

@chalasr Done

Copy link
Member

@chalasrchalasr left a comment

Choose a reason for hiding this comment

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

Nice work

@chalasr
Copy link
Member

fabbot's suggestion looks legit, can you apply it?

@HypeMC
Copy link
MemberAuthor

$names = array_unique(['default', ...$serializerNames]);
}

if ($tag['built-in'] ?? false) {
Copy link
Member

Choose a reason for hiding this comment

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

To be consistent with the code base (likeextended_type for Forms), I think it should be:

Suggested change
if ($tag['built-in'] ??false) {
if ($tag['built_in'] ??false) {

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

@HypeMCHypeMCforce-pushed thenamed-serializers branch 2 times, most recently fromaee8227 toca834e5CompareSeptember 19, 2024 09:01
@fabpot
Copy link
Member

Thank you@HypeMC.

jdreesen, HypeMC, and juricaskorin reacted with hooray emoji

@fabpotfabpot merged commitce228d3 intosymfony:7.2Sep 19, 2024
4 of 6 checks passed
@HypeMCHypeMC deleted the named-serializers branchSeptember 19, 2024 09:17
@fabpotfabpot mentioned this pull requestOct 27, 2024
ruudk added a commit to ruudk/symfony that referenced this pull requestJan 27, 2025
Named serializers were introduced insymfony#56823 and they work great.We noticed a small bug when using custom name convertors.The MimeMessageNormalizer holds a reference to `serializer.normalizer.property`.But when using named serializers, it would use the specific child normalizer instead.With this change, we fix this problem for any service that starts with `serializer.normalizer.`.
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@fabpotfabpotfabpot approved these changes

@dunglasdunglasdunglas approved these changes

@mtarldmtarldmtarld approved these changes

@chalasrchalasrchalasr approved these changes

@stofstofAwaiting requested review from stof

Assignees
No one assigned
Projects
None yet
Milestone
7.2
Development

Successfully merging this pull request may close these issues.

8 participants
@HypeMC@carsonbot@dunglas@stof@chalasr@fabpot@mtarld@OskarStark

[8]ページ先頭

©2009-2025 Movatter.jp