Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[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

Merged
merged 1 commit into from
Oct 5, 2018
Merged

[Serialized] allow configuring the serialized name of properties through metadata #28505

merged 1 commit into from
Oct 5, 2018

Conversation

fbourigault
Copy link
Contributor

@fbourigault fbourigault commented Sep 18, 2018

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

  • add a CHANGELOG.md entry.
  • add a fallback.
  • add framework integration.
  • add local caching to MetadataAwareNameConverter.
  • add a doc PR.

Copy link
Member

@Nyholm Nyholm left a 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
Copy link
Member

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()
Copy link
Member

Choose a reason for hiding this comment

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

: string

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.

Awesome!

*
* @author Fabien Bourigault <[email protected]>
*/
class SerializedName
Copy link
Member

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)
Copy link
Member

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()
Copy link
Member

Choose a reason for hiding this comment

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

getSerializedName(): string

Copy link
Contributor Author

Choose a reason for hiding this comment

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

getSerializedName(): ?string?

Copy link
Member

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);
Copy link
Member

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
Copy link
Member

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)


$attributesMetadata = $classMetadata->getAttributesMetadata();

foreach ($attributesMetadata as $name => $metadata) {
Copy link
Member

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?

@dunglas
Copy link
Member

dunglas commented Sep 18, 2018

I think you can add the FrameworkBundle integration in the same PR (but another one is ok too).

@nicolas-grekas nicolas-grekas added this to the next milestone Sep 19, 2018
@fbourigault
Copy link
Contributor Author

I would like to start documenting this feature but I don't know where to start. Can someone help me to write it?

@Nyholm
Copy link
Member

Nyholm commented Sep 24, 2018

How about adding it on a new subsection to https://symfony.com/doc/current/components/serializer.html#converting-property-names-when-serializing-and-deserializing

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.

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" >
Copy link
Member

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 -->
Copy link
Member

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",
Copy link
Member

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;
Copy link
Member

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())
Copy link
Member

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);
Copy link
Member

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?

Copy link
Member

Choose a reason for hiding this comment

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

OK, internal interface.

@nicolas-grekas nicolas-grekas changed the title [Serialized] Serialized name [Serialized] allow configuring the serialized name of properties through metadata Oct 3, 2018
@dunglas
Copy link
Member

dunglas commented Oct 5, 2018

Thanks for your work on this new feature!

@dunglas dunglas merged commit d1d1ceb into symfony:master Oct 5, 2018
dunglas added a commit that referenced this pull request Oct 5, 2018
…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
@fbourigault fbourigault deleted the serialized-name branch October 5, 2018 07:47
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Oct 25, 2018
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
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
This was referenced Nov 3, 2018
@jperovic
Copy link
Contributor

jperovic commented Dec 5, 2019

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 Person class with following fields: id, name and naturalId. My use-case requires me to map incoming id to naturalId and leave id to NULL.

For me, it did not work, though, I am still unsure if I initialized the serializer service properly.

@jperovic
Copy link
Contributor

jperovic commented Dec 6, 2019

Oh, scratch that. Indeed, this was a misconfiguration on my part. (I was missing @Groups() annotation)

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.

6 participants