279dc46756
This PR was squashed before being merged into the 4.1-dev branch (closes #24375).
Discussion
----------
[Serializer] Serialize and deserialize from abstract classes
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | ø
| License | MIT
| Doc PR | Not yet
This PR adds a feature in the Serializer: allow to serialize and de-serialize abstract classes. Such feature is especially useful when dealing with domain objects.
# Example
Let's take the example of the following objects:
- `CodeRepository` defines a set of properties like `name` and `url`
- `GitHubCodeRepository` and `BitBucketCodeRepository` extends from the abstract `CodeRepository` class and adds a few properties.
- `Project` has a relation with a `codeRepository`, which has a type `CodeRepository`.
At the moment, the serializer can't serialize/deserialize correctly this `Project` object has it doesn't know how to deal with this `CodeRepository` abstract object.
This feature allows the serializer to deal with such situation. The `ObjectNormalizer` has now access to a `ClassDiscriminatorResolver` that knows, for a given abstract class:
- Is the "type" property it needs to read/write to uniquely identify each sub-class
- What's the name of the "type" for each sub-class mapping
# Usage without Framework Bundle
```php
$discriminatorResolver = new ClassDiscriminatorResolver();
$discriminatorResolver->addClassMapping(CodeRepository::class, new ClassDiscriminatorMapping('type', [
'github' => GitHubCodeRepository::class,
'bitbucket' => BitBucketCodeRepository::class,
]));
$serializer = new Serializer(array(new ObjectNormalizer(null, null, null, null, $discriminatorResolver)), array('json' => new JsonEncoder()));
$serialized = $serializer->serialize(new GitHubCodeRepository());
// {"type": "github"}
$repository = $serializer->unserialize($serialized, CodeRepository::class, 'json');
// GitHubCodeRepository
```
# Usage with the Framework Bundle
```yaml
framework:
serializer:
discriminator_class_mapping:
App\CodeRepository:
type_property: type
mapping:
github: App\GitHubCodeRepository
bitbucket: App\BitBucketCodeRepository
```
# Usage with Annotations/XML/YAML
```php
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/**
* @DiscriminatorMap(typeProperty="type", mapping={
* "first"="Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild",
* "second"="Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild"
* })
*/
abstract class AbstractDummy
{
public $foo;
public function __construct($foo = null)
{
$this->foo = $foo;
}
}
```
# TODO
- [x] Working as standalone
- [x] Working with the framework bundle
- [x] Tests on mapping classes
Commits
-------
|
||
---|---|---|
.. | ||
CacheWarmer | ||
Command | ||
Console | ||
Controller | ||
DataCollector | ||
DependencyInjection | ||
EventListener | ||
HttpCache | ||
Kernel | ||
Resources | ||
Routing | ||
Templating | ||
Test | ||
Tests | ||
Translation | ||
.gitignore | ||
CHANGELOG.md | ||
Client.php | ||
composer.json | ||
FrameworkBundle.php | ||
LICENSE | ||
phpunit.xml.dist | ||
README.md |