Skip to content

[Serializer] Add the possibility to filter attributes #18834

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
Feb 13, 2017

Conversation

dunglas
Copy link
Member

@dunglas dunglas commented May 22, 2016

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

This new features give the possibility to the end user to select select fields to normalize.

Exemple:

class Foo
{
    public $a = '1';
    public $b = '2';
    public $c = '3';
}

$normalizer = new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer();
$normalizer->normalize(new Foo(), null, ['attributes' => ['a', 'c']]);
// ['a' => '1', 'c' => '3']

Denormalization is also supported. This feature works for any normalizer using the Symfony\Component\Serializer\Normalizer\AbstractNormalizer class.

The main use case is to permit to API clients to optimize responses length by dropping unnecessary information like in the following example:

http://exemple.com/cars?fields=a,c

{'a' => 1, 'c' => 2}

Nested parameters are also supported:

class Foo
{
    public $a = '1';
    public $b = '2';
    public $c = '3';
    public $bar = new Bar();
}

class Bar
{
    public $x = 'x';
    public $y = 'y';
    public $z = 'z';
}

$serializer = new \Symfony\Component\Serializer(
    [new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer()]
);
$serializer->normalize(new Foo(), null, ['attributes' => ['a', 'c', 'bar' => ['y']]]);
// ['a' => '1', 'c' => '3', 'bar' => ['y' => 'y']

Thanks to this PR, support for this feature will be available out of the box in API Platform.

@GuilhemN
Copy link
Contributor

GuilhemN commented May 22, 2016

Your example in the description is wrong, the context should be a nested array ['attributes' => ['a', 'c']].
Otherwise, this looks great!

@Simperfit
Copy link
Contributor

👍

@dunglas
Copy link
Member Author

dunglas commented May 22, 2016

Good catch @Ener-Getick, thanks!

@theofidry
Copy link
Contributor

theofidry commented May 22, 2016

Is there a support for nested attributes as well? Example:

class Foo {
  public $bar;

  public function __construct(Bar $bar) {
    $this->bar = $bar;
  }
}

class Bar {
  public $a = 1;
  public $b = 2;
}

$normalizer = new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer();
$normalizer->normalize(new Foo(new Bar()), null, ['attributes' => ['bar.a']]);
// => ['bar.a' => 1]

@GuilhemN
Copy link
Contributor

GuilhemN commented Jun 7, 2016

@theofidry no this isn't possible.

@dunglas maybe an associative array could be used to allow nested attributes safely ?

[
    'attributes' => [
        'a' => [
            'b' => [], 'c' => [ 'd' ]
        ],
        'e' => []
    ]
]

BTW there are no bc breaks/deprecations in this PR, so this can be removed from the pr header.

@fabpot
Copy link
Member

fabpot commented Jun 16, 2016

Sounds like a good new feature. @dunglas Can you finish it?

@fabpot
Copy link
Member

fabpot commented Sep 14, 2016

Any news?

@dunglas
Copy link
Member Author

dunglas commented Sep 14, 2016

Yes I've an idea of how to manage related entities. I'll finish this one ASAP.

@teohhanhui
Copy link
Contributor

I think it's crucial to have nested attributes support, and in a nice syntax. Perhaps using PropertyAccess path...

The semantics could be something like this: If one attribute is specified for a certain object / item, then all attributes on the same object / item need to be specified (otherwise they will be omitted). Similar to how Prophecy mocks work.

@xabbuh
Copy link
Member

xabbuh commented Dec 28, 2016

Making use of the PropertyAccess component for this feature sounds like a good idea to me.

@dunglas dunglas force-pushed the serializer_attributes branch from f7b9ca8 to 527bc77 Compare February 3, 2017 18:21
@dunglas
Copy link
Member Author

dunglas commented Feb 3, 2017

I eventually added support for nested attributes (it works for normalization and denormalization).

Usage:

class Foo
{
    public $a = '1';
    public $b = '2';
    public $c = '3';
    public $bar = new Bar();
}

class Bar
{
    public $x = 'x';
    public $y = 'y';
    public $z = 'z';
}

$serializer = new \Symfony\Component\Serializer(
    [new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer()]
);
$serializer->normalize(new Foo(), null, ['attributes' => ['a', 'c', 'bar' => ['y']]]);
// ['a' => '1', 'c' => '3', 'bar' => ['y' => 'y']

This PR is ready now. ping @symfony/deciders

@dunglas dunglas modified the milestones: 3.3, 3.x Feb 4, 2017
@dunglas dunglas force-pushed the serializer_attributes branch from cebc036 to b3826fb Compare February 13, 2017 10:26
@nicolas-grekas nicolas-grekas changed the title [Serializer] Add the possibilitiy to filter attributes [Serializer] Add the possibility to filter attributes Feb 13, 2017
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.

👍

@fabpot
Copy link
Member

fabpot commented Feb 13, 2017

@dunglas Can you submit a PR on the docs?

@fabpot
Copy link
Member

fabpot commented Feb 13, 2017

Thank you @dunglas.

@fabpot fabpot merged commit b3826fb into symfony:master Feb 13, 2017
fabpot added a commit that referenced this pull request Feb 13, 2017
…(dunglas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Serializer] Add the possibility to filter attributes

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

This new features give the possibility to the end user to select select fields to normalize.

Exemple:

``` php
class Foo
{
    public $a = '1';
    public $b = '2';
    public $c = '3';
}

$normalizer = new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer();
$normalizer->normalize(new Foo(), null, ['attributes' => ['a', 'c']]);
// ['a' => '1', 'c' => '3']
```

Denormalization is also supported. This feature works for any normalizer using the `Symfony\Component\Serializer\Normalizer\AbstractNormalizer` class.

The main use case is to permit to API clients to optimize responses length by dropping unnecessary information like in the following example:

```
http://exemple.com/cars?fields=a,c

{'a' => 1, 'c' => 2}
```

Thanks to this PR, support for this feature will be available out of the box in [API Platform](https://api-platform.com).

Commits
-------

b3826fb [Serializer] Add the possibility to filter attributes
@dunglas dunglas deleted the serializer_attributes branch February 13, 2017 14:34
@fabpot fabpot mentioned this pull request May 1, 2017
fabpot added a commit that referenced this pull request Dec 7, 2017
…(dunglas)

This PR was merged into the 3.3 branch.

Discussion
----------

[Serializer] Unset attributes when creating child context

 | Q             | A
 | ------------- | ---
 | Branch?       | 3.3
 | Bug fix?      | yes
 | New feature?  | no
 | BC breaks?    | no
 | Deprecations? | no
 | Tests pass?   | yes
 | Fixed tickets | n/a
 | License       | MIT
 | Doc PR        | n/a

In some cases, the `attributes` key isn't overrode when creating the context passed to nested normalizers.
 It's definitely a bug, but an attacker cannot access to non public data (ignored attributes are checked before the `attributes` key). However some data that must be public may be missing as highlighted by the test.

I've introduced the initial bug here: #18834

Commits
-------

4ff9d99 [Serializer] Unset attributes when creating child context
weaverryan added a commit to symfony/symfony-docs that referenced this pull request Dec 13, 2017
…as, javiereguiluz)

This PR was merged into the 3.3 branch.

Discussion
----------

[Serializer] Add docs for attributes context key

Documentation for symfony/symfony#18834

Commits
-------

d48d6d4 Minor reword
ea211ab Review
5d75696 [Serializer] Add docs for attributes context key
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.

10 participants