Skip to content
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] Serialization groups support #12092

Merged
merged 1 commit into from Dec 21, 2014

Conversation

Projects
None yet
7 participants
@dunglas
Copy link
Member

commented Oct 1, 2014

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
License MIT
Doc PR symfony/symfony-docs#4675

This PR is a first attempt adding serialization groups to the Serializer component. Btw, it also add supports of ignored attributes for denormalization (only normalization is currently supported).

Groups support is totally optional and is not enabled by default (in that case, the Serializer will have the current behavior). No BC spotted for now.

To use it:

use Symfony\Component\Serializer\Annotation\Groups;

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;

class MyObj
{
    /**
     * @Groups({"group1", "group2"})
     */
    public $foo;
    /**
     * @Groups({"group3"})
     */
    public $bar;
}

$obj = new MyObj();
$obj->foo = 'foo';
$obj->bar = 'bar';

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new PropertyNormalizer($classMetadataFactory);

$serializer = new Serializer([$normalizer]);
$data = $serializer->normalize($obj, null, ['groups' => ['group1']]);
// $data = ['foo' => 'foo'];

$obj2 = $serializer->denormalize(['foo' => 'foo', 'bar' => 'bar'], 'MyObj', null, ['groups' => ['group1', 'group3']);
// $obj2 = MyObj(foo: 'foo', bar: 'bar')

Some work still need to be done:

  • Add XML mapping
  • Add YAML mapping
  • Refactor tests

The ClassMetadata code is largely inspired from the code of the Validator component. Duplicated code in PropertyNormalizer and GetSetMethodNormalizer has been moved in a new AbstractNormalizer class.

This PR also make the interface of PropertyNormalizer fluent (like the current behavior of GetSetMethodNormalizer.

@dunglas dunglas force-pushed the dunglas:serializer_groups branch from b405e14 to 86c81a1 Oct 1, 2014

@ProPheT777

This comment has been minimized.

Copy link
Contributor

commented Oct 1, 2014

👎

The serializer Symfony meets the needs, and that's enough (well I think), and for further applications, there JMSSerializer exists, and have an exellent approach to resolve this problematic. I find that having a "simple" serializer (sf) and serializer under "Steroid" (jms) is good. What is the motivation to add this kind of functionality?

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 1, 2014

@ProPheT777 the initial motivation is adding groups support to HydraBundle. Of course this can be done directly in that bundle but as the code is generic and will work with any encoder (Hydra or anything else) I've opened this PR here. Note that this does not break BC and that groups support is not enabled by default. Pass no parameter to the normalizer's constructor and the Serializer will behave exactly as before.

Other motivations are:

  • have a powerful MIT serializer (JMSSerializer is under Apache license, so we cannot use it in a GPLv2 project - and it's my case)
  • have all tools needed to easily create REST APIs directly in Symfony (and groups support or something similar is a must have)

And btw, the Serializer currently does not meet the need. Circular references are not handled and serializing a typical set of entities can lead to an infinite loop. I'll submit a PR to fix that soon.

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 1, 2014

About the licensing issue see symfony/symfony-standard#535

$metadata->addAttributeGroup(lcfirst($matches[2]), $group);
}
} else {
throw new \BadMethodCallException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".', $className, $method->name));

This comment has been minimized.

Copy link
@stof

stof Oct 2, 2014

Member

looks like you copied the code from the Validator component without being careful about changing it to you needs

This comment has been minimized.

Copy link
@dunglas

dunglas Oct 2, 2014

Author Member

You're right!
I'll change the exception message.

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 2, 2014

@stof fixed.

@stof stof added the Serializer label Oct 6, 2014

@dunglas dunglas changed the title [WIP] [Serializer] Serialization groups support [Serializer] Serialization groups support Oct 6, 2014

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 6, 2014

This PR is almost done. I've added a YAML and a XML loader.
Something still bothers me: some code (especially LoaderChain) is almost copy/pasted from the Validation component. Should it be refactored?

@stof

This comment has been minimized.

Copy link
Member

commented Oct 7, 2014

@dunglas we have the time to figure a way to handle this, given that it won't be part of 2.6 (we have reach the feature freeze)

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 7, 2014

I've looked more in depth to this piece of code. Only LoaderChain is duplicated and it's only 50 lines of very generic code. Other loaders are similar in structure but have different responsibilities (because serializer's metadata have nothing to do with validator's metadata).
It seems acceptable to me to duplicate this particular (LoaderChain) small piece of code.

@lsmith77

This comment has been minimized.

Copy link
Contributor

commented Oct 20, 2014

btw .. need a rebase now

@dunglas dunglas force-pushed the dunglas:serializer_groups branch from 4bd6281 to e07a109 Oct 20, 2014

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Oct 20, 2014

Rebased.

@dunglas dunglas force-pushed the dunglas:serializer_groups branch from 490946d to dcf1d97 Dec 11, 2014

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 11, 2014

Rebased against master. Any update about the status of this PR now that 2.6 has been released?

@fabpot

This comment has been minimized.

Copy link
Member

commented Dec 12, 2014

I agree with @dunglas that getting a better serializer in code in a good idea for reasons he explained above; of course, we need to keep the current philosophy of the component.

Seeing that @dunglas is investing a lot of time in this component with great ideas and PRs, no one is really maintaining this component, I propose to let him move the component forward. What do you think @lsmith77 @Seldaek?

@lsmith77

This comment has been minimized.

Copy link
Contributor

commented Dec 12, 2014

+1 .. I have full trust in him

@Seldaek

This comment has been minimized.

Copy link
Member

commented Dec 12, 2014

+1 for me too, run with it and do great things! :)

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 13, 2014

😺

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 15, 2014

@fabpot It's possible to host the new xsd on symfony.com to make Travis happy?

@fabpot

This comment has been minimized.

Copy link
Member

commented Dec 21, 2014

@dunglas I think the next step would be to open a PR on the docs as it needs to be documented before merge.

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 21, 2014

@fabpot

This comment has been minimized.

Copy link
Member

commented Dec 21, 2014

Thank you @dunglas.

@fabpot fabpot merged commit dcf1d97 into symfony:master Dec 21, 2014

1 of 2 checks passed

continuous-integration/travis-ci The Travis CI build could not complete due to an error
Details
default Your code looks good.
Details

fabpot added a commit that referenced this pull request Dec 21, 2014

feature #12092 [Serializer] Serialization groups support (dunglas)
This PR was merged into the 3.0-dev branch.

Discussion
----------

[Serializer] Serialization groups support

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT
| Doc PR        | symfony/symfony-docs#4675

This PR is a first attempt adding serialization groups to the `Serializer` component. Btw, it also add supports of ignored attributes for denormalization (only normalization is currently supported).

Groups support is totally optional and is not enabled by default (in that case, the `Serializer` will have the current behavior). No BC spotted for now.

To use it:
```php
use Symfony\Component\Serializer\Annotation\Groups;

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;

class MyObj
{
    /**
     * @groups({"group1", "group2"})
     */
    public $foo;
    /**
     * @groups({"group3"})
     */
    public $bar;
}

$obj = new MyObj();
$obj->foo = 'foo';
$obj->bar = 'bar';

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new PropertyNormalizer($classMetadataFactory);

$serializer = new Serializer([$normalizer]);
$data = $serializer->normalize($obj, null, ['groups' => ['group1']]);
// $data = ['foo' => 'foo'];

$obj2 = $serializer->denormalize(['foo' => 'foo', 'bar' => 'bar'], 'MyObj', null, ['groups' => ['group1', 'group3']);
// $obj2 = MyObj(foo: 'foo', bar: 'bar')
```

Some work still need to be done:
- [x] Add XML mapping
- [x] Add YAML mapping
- [x] Refactor tests

The `ClassMetadata` code is largely inspired from the code of the `Validator` component. Duplicated code in `PropertyNormalizer` and `GetSetMethodNormalizer` has been moved in a new `AbstractNormalizer` class.

This PR also make the interface of `PropertyNormalizer` fluent (like the current behavior of `GetSetMethodNormalizer`.

Commits
-------

dcf1d97 [Serializer] Serialization groups support
@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 21, 2014

Can this feature be merged in 2.7?

@fabpot

This comment has been minimized.

Copy link
Member

commented Dec 21, 2014

done

fabpot added a commit that referenced this pull request Dec 21, 2014

feature #12092 [Serializer] Serialization groups support (dunglas)
This PR was submitted for the master branch but it was merged into the 2.7 branch instead (closes #12092).

Discussion
----------

[Serializer] Serialization groups support

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT
| Doc PR        | symfony/symfony-docs#4675

This PR is a first attempt adding serialization groups to the `Serializer` component. Btw, it also add supports of ignored attributes for denormalization (only normalization is currently supported).

Groups support is totally optional and is not enabled by default (in that case, the `Serializer` will have the current behavior). No BC spotted for now.

To use it:
```php
use Symfony\Component\Serializer\Annotation\Groups;

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;

class MyObj
{
    /**
     * @groups({"group1", "group2"})
     */
    public $foo;
    /**
     * @groups({"group3"})
     */
    public $bar;
}

$obj = new MyObj();
$obj->foo = 'foo';
$obj->bar = 'bar';

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new PropertyNormalizer($classMetadataFactory);

$serializer = new Serializer([$normalizer]);
$data = $serializer->normalize($obj, null, ['groups' => ['group1']]);
// $data = ['foo' => 'foo'];

$obj2 = $serializer->denormalize(['foo' => 'foo', 'bar' => 'bar'], 'MyObj', null, ['groups' => ['group1', 'group3']);
// $obj2 = MyObj(foo: 'foo', bar: 'bar')
```

Some work still need to be done:
- [x] Add XML mapping
- [x] Add YAML mapping
- [x] Refactor tests

The `ClassMetadata` code is largely inspired from the code of the `Validator` component. Duplicated code in `PropertyNormalizer` and `GetSetMethodNormalizer` has been moved in a new `AbstractNormalizer` class.

This PR also make the interface of `PropertyNormalizer` fluent (like the current behavior of `GetSetMethodNormalizer`.

Commits
-------

57a191b [Serializer] Serialization groups support
@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 21, 2014

Thanks!

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 24, 2014

@fabpot can you upload the XSD at the following URL http://symfony.com/schema/dic/services/services-1.0.xsd to make the XmlFileLoader working?

Thanks!

@wouterj

This comment has been minimized.

Copy link
Member

commented Dec 24, 2014

@dunglas the file loader is not based on the XSD on that url, but instead on the XSD downloaded with symfony.

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 24, 2014

@wouterj not yet for the serializer but I'll add it soon.

@dunglas

This comment has been minimized.

Copy link
Member Author

commented Dec 25, 2014

@wouterj sorry I'm wrong and you're right. The feature is present but tests use a wrong (old) XML format (#13108).

weaverryan added a commit to symfony/symfony-docs that referenced this pull request May 22, 2015

feature #4675 [Serializer] Doc for groups support (dunglas)
This PR was merged into the 2.7 branch.

Discussion
----------

[Serializer] Doc for groups support

| Q                | A
| --------------- | ---
| Doc fix?      | no
| New docs? | yes symfony/symfony#12092
| Applies to   | 2.7

This is the documentation for serialization groups support.

Commits
-------

e417395 [Serializer] Fix CS
ae2b78c [Serializer] Add getter group example
745f412 [Serializer] Doc for groups support

@dunglas dunglas deleted the dunglas:serializer_groups branch Dec 5, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.