-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] ObjectNormalizer #13257
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
[Serializer] ObjectNormalizer #13257
Conversation
If you want to play with this new normalizer (or hack it), I've created a branch including all Serializer PR waiting to be merged (including this one): https://github.com/dunglas/symfony/tree/new_serializer To use it in a standard edition install, add the following lines to your "repositories": [
{
"type": "vcs",
"url": "https://github.com/dunglas/symfony"
}
], Then replace with Symfony line to use this experimental branch: "symfony/symfony": "dev-new_serializer as 2.7.0", |
hi @dunglas, can you provide a practical sample of what this feature can do ? |
class MyObj
{
public $foo = 'foo';
public getBar()
{
return 'bar';
}
public isBaz()
{
return true;
}
}
$normalizer = new \Symfony\Component\Serializer\Normalizer\PropertyAccessNormalizer();
var_dump($normalizer->normalize(new MyObj()));
// Should output something like ['foo' => 'foo', 'bar' => 'bar', 'baz' => true] |
This normalizer also supports denormalization (for gettters / setters and properties), serialization groups (http://symfony.com/blog/new-in-symfony-2-7-serialization-groups), name converters (symfony/symfony-docs#4692), circular references handlers (symfony/symfony-docs#4299) and existing object population (#13252). |
👍 The only "issue" I see is the name; I understand that you named your class after the property access component but I find it confusing as at first, I thought it was about "just" supporting class properties. If it becomes the default one (which I think is a good idea), we should find a better name. |
I agree, the name is confusing. What about |
@dunglas If this is the "definitive" serializer, that sounds much better to me. |
totaly agree with @fabpot , this should become the default serializer! |
@@ -28,7 +28,8 @@ | |||
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", | |||
"doctrine/cache": "For using the default cached annotation reader and metadata cache.", | |||
"symfony/yaml": "For using the default YAML mapping loader.", | |||
"symfony/config": "For using the XML mapping loader." | |||
"symfony/config": "For using the XML mapping loader.", | |||
"symfony/property-access": "For using the property access 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.
Shouldn't this be moved to require
if it becomes the default 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.
This should be the default serializer in the full stack framework, but please don't add more "hard" dependencies between (standalone) components !
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.
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.
@mickaelandrieu good point
What do you think about moving the code listing accessible "properties" (trough public properties and methods) - https://github.com/dunglas/symfony/blob/seriaizer_property_access_normalizer/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php#L62-L89 - in the PropertyAccess Component? It can be useful in other contexts (in fact, I've an use case in a private project right now). cc @fabpot @webmozart |
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; | ||
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy; | ||
|
||
require_once __DIR__.'/../../Annotation/Groups.php'; |
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 should rely on autoloading instead
b344af7
to
2f69022
Compare
7531332
to
e1cf645
Compare
Rebased. Should be ready for the merge now. |
@@ -28,7 +29,8 @@ | |||
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", | |||
"doctrine/cache": "For using the default cached annotation reader and metadata cache.", | |||
"symfony/yaml": "For using the default YAML mapping loader.", | |||
"symfony/config": "For using the XML mapping loader." | |||
"symfony/config": "For using the XML mapping loader.", | |||
"symfony/property-access": "For using the ObjectNormalizer." |
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.
👍 thanks a lot!
I've fixed tests with |
continue; | ||
} | ||
|
||
$attributeValue = $this->propertyAccessor->getValue($object, $attribute); |
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 on purpose you don't use an else
block on the next statement? It can avoid a call to the this->propertyAccessor->getValue
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.
@jeremy-derusse I don't understand what you mean.
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 can replace
$attributeValue = $this->propertyAccessor->getValue($object, $attribute);
if (array_key_exists($attribute, $this->callbacks)) {
$attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue);
}
by
if (array_key_exists($attribute, $this->callbacks)) {
$attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue);
} else {
$attributeValue = $this->propertyAccessor->getValue($object, $attribute);
}
and avoid to call $this->propertyAccessor->getValue($object, $attribute);
when array_key_exists($attribute, $this->callbacks)
is false.
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.
No because $attributeValue
in $attributeValue = call_user_func($this->callbacks[$attribute], $attributeValue);
will be undefined.
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.
Or worse, the value of the previous loop iteration.
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 I got it. But still no because the attribute value will never be retrieved. We need it even if a callback is not registered.
a562e42
to
a4b6421
Compare
fca94f2
to
6a12f1e
Compare
Rebased. |
ping @symfony/deciders |
6a12f1e
to
0050bbb
Compare
This PR was merged into the 2.7 branch. Discussion ---------- [Serializer] ObjectNormalizer | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | License | MIT | Doc PR | not yet `PropertyAccessNormalizer` is a new normalizer leveraging the PropertyAccess Component. It is able to handle classes containing both public properties and properties only accessibles trough getters / setters / issers / hassers... As it extends `AbstractNormalizer`, it supports circular reference handling, name converters and existing object population. What do you think about making this new normalizer the default one as it's the most convenient to use and the most consistent with the behavior of other components. #13120, #13252 and #13255 need to be merged to make this PR working. Commits ------- 0050bbb [Serializer] Introduce ObjectNormalizer
👍 thanks for this improvement @dunglas ! |
…nnotations (dunglas) This PR was merged into the 2.7 branch. Discussion ---------- [Serializer] Supports hassers and setters for groups annotations | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a For more coherence with the new `ObjectNormalizer` (#13257), this PR allows to add `@Groups` annotations on hasser and setter methods too. Commits ------- 9c87ecc [Serializer] Supports hassers and setters for groups annotations
PropertyAccessNormalizer
is a new normalizer leveraging the PropertyAccess Component. It is able to handle classes containing both public properties and properties only accessibles trough getters / setters / issers / hassers...As it extends
AbstractNormalizer
, it supports circular reference handling, name converters and existing object population.What do you think about making this new normalizer the default one as it's the most convenient to use and the most consistent with the behavior of other components.
#13120, #13252 and #13255 need to be merged to make this PR working.