-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serialized] allow configuring the serialized name of properties through metadata #28505
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
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 great. Thank you for working on #19374.
I did a quick review and I found some minor things.
class SerializedName | ||
{ | ||
/** | ||
* @var int |
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 be string
$this->serializedName = $data['value']; | ||
} | ||
|
||
public function getSerializedName() |
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.
: string
src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php
Show resolved
Hide resolved
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.
Awesome!
* | ||
* @author Fabien Bourigault <[email protected]> | ||
*/ | ||
class SerializedName |
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.
final
?
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function setSerializedName($serializedName) |
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.
setSerializedName(string $serializedName = null)
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getSerializedName() |
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.
getSerializedName(): string
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.
getSerializedName(): ?string
?
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.
indeed
* | ||
* @param string|null $serializedName | ||
*/ | ||
public function setSerializedName($serializedName); |
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.
setSerializedName(string $serializedName = null);
final class MetadataAwareNameConverter implements AdvancedNameConverterInterface | ||
{ | ||
/** | ||
* @var ClassMetadataFactoryInterface |
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.
Can be removed (IDE will infer it from the constructor's typehint)
src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php
Outdated
Show resolved
Hide resolved
|
||
$attributesMetadata = $classMetadata->getAttributesMetadata(); | ||
|
||
foreach ($attributesMetadata as $name => $metadata) { |
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.
Can you cache this in a private static property to avoid looping for every property?
src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php
Outdated
Show resolved
Hide resolved
I think you can add the FrameworkBundle integration in the same PR (but another one is ok too). |
I would like to start documenting this feature but I don't know where to start. Can someone help me to write it? |
How about adding it on a new subsection to https://symfony.com/doc/current/components/serializer.html#converting-property-names-when-serializing-and-deserializing |
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.
Awesome new feature! Just a few remaining comments, then 👍 on my side.
@@ -119,6 +119,11 @@ | |||
<!-- Name converter --> | |||
<service id="serializer.name_converter.camel_case_to_snake_case" class="Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter" /> | |||
|
|||
<service id="serializer.name_converter.metadata" class="Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter" > |
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.
Wouldn't serializer.name_converter.metadata_aware
be more explicit?
@@ -119,6 +119,11 @@ | |||
<!-- Name converter --> | |||
<service id="serializer.name_converter.camel_case_to_snake_case" class="Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter" /> | |||
|
|||
<service id="serializer.name_converter.metadata" class="Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter" > | |||
<argument type="service" id="serializer.mapping.class_metadata_factory"/> | |||
<argument>null</argument> <!-- fallback name converter --> |
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.
As it's the last one, it can be omitted.
@@ -45,7 +45,7 @@ | |||
"symfony/process": "~3.4|~4.0", | |||
"symfony/security-core": "~3.4|~4.0", | |||
"symfony/security-csrf": "~3.4|~4.0", | |||
"symfony/serializer": "^4.1", | |||
"symfony/serializer": "^4.2", |
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.
Personally, I'm ok to bump this dependency. But feature detection may be used to support both versions. WDYT @symfony/deciders?
* class' serialized representation. Do not access it. Use | ||
* {@link getSerializedName()} instead. | ||
*/ | ||
public $serializedName; |
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.
Is it still really necessary to make this property public? We do that everywhere in validator (and I copied this behavior in Serializer), but I'm not sure that it's still accurate.
Anyway, keep it here for consistency.
return null; | ||
} | ||
|
||
private function denormalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = array()) |
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.
: string
?
/** | ||
* Sets the serialization name for this attribute. | ||
*/ | ||
public function setSerializedName(string $serializedName = null); |
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.
BC break? why not otherwise?
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.
OK, internal interface.
Thanks for your work on this new feature! |
…properties through metadata (fbourigault) This PR was squashed before being merged into the 4.2-dev branch (closes #28505). Discussion ---------- [Serialized] allow configuring the serialized name of properties through metadata | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #15171 | License | MIT | Doc PR | symfony/symfony-docs#10422 This leverage the new `AdvancedNameConverterInterface` interface (#27021) to implement a name converter that relies on metadata. The name to use is configured per property using a `@SerializedName` annotation or the `serialized-name` XML attribute or the `serialized_name` key for YAML. This was exposed by @dunglas in #19374 (comment). # Framework integration For FramworkBundle integration, a ChainNameConverter could be added to allow users to use this name converter with a custom one. # To do - [x] add a CHANGELOG.md entry. - [x] add a fallback. - [x] add framework integration. - [x] add local caching to `MetadataAwareNameConverter`. - [x] add a doc PR. Commits ------- d1d1ceb [Serialized] allow configuring the serialized name of properties through metadata
This PR was merged into the master branch. Discussion ---------- Document metadata aware name conversion Documentation for symfony/symfony#28505. I wrote this section with strong inspiration from the discriminator section. # To do - [ ] Add an introduction Commits ------- 9d50c77 document metadata aware name conversion
Just found myself in a scenario where I could use it, but keep wondering if this is indeed applicable for deserialization. For example: {
"id": 123,
"name": "Jovan"
} And I have my For me, it did not work, though, I am still unsure if I initialized the |
Oh, scratch that. Indeed, this was a misconfiguration on my part. (I was missing |
This leverage the new
AdvancedNameConverterInterface
interface (#27021) to implement a name converter that relies on metadata. The name to use is configured per property using a@SerializedName
annotation or theserialized-name
XML attribute or theserialized_name
key for YAML.This was exposed by @dunglas in #19374 (comment).
Framework integration
For FramworkBundle integration, a ChainNameConverter could be added to allow users to use this name converter with a custom one.
To do
MetadataAwareNameConverter
.