Samuel Roze

When working with objects that are pretty similar or share lots of properties,
is common to use interfaces or . The problem with that
extend from other abstract classes is that the Serializer component doesn17;t
know how to / them correctly.

In 4.1, we improved the Serializer component to support this feature
using a “discriminator class mapping”. Consider an application that defines an
abstract CodeRepository class extended by GitHubCodeRepository and
BitBucketCodeRepository classes. This example shows how to serialize and
deserialize those objects when using the stand-alone Serializer component:

 1
 2
 3
 4
 5
 6
 7
 8
 9

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ...

$discriminator = new ClassDiscriminatorResolver();
// $type is the property used to differentiate between classes
$discriminator->addClassMapping(
    CodeRepository::class,
    new ClassDiscriminatorMapping('type', [
        'github' => GitHubCodeRepository::class,
        'bitbucket' => BitBucketCodeRepository::class,
    ])
);

// pass the discriminator as the last argument of the normalizer
$serializer = new Serializer(
    array(new ObjectNormalizer(null, null, null, null, $discriminator)),
    array('json' => new JsonEncoder())
);

// when serializing, the discriminator knows that the value of the "type"
// property for GitHubCodeRepository classes must be set to {"type": "github"}
$serialized = $serializer->serialize(new GitHubCodeRepository());

// when deserializing into the abstract CodeRepository class, the discriminator
// uses the "type" value to know that $repository must be an instance of GitHubCodeRepository
$repository = $serializer->unserialize($serialized, CodeRepository::class, 'json');

When using this feature in a Symfony application, you can simply configure all
this in a YAML or XML file and even using PHP annotations:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
namespace AppRepository;

use SymfonyComponentSerializerAnnotationDiscriminatorMap;

/**
 * @DiscriminatorMap(typeProperty="type", mapping={
 *    "github"="AppRepositoryGitHubCodeRepository",
 *    "bitbucket"="AppRepositoryBitBucketCodeRepository"
 * })
 */
interface CodeRepository
{
    // ...
}

You can read more about this new feature in the Serializing Interfaces and Abstract Classes
section of the Serializer Component documentation.



Source link

LEAVE A REPLY

Please enter your comment!
Please enter your name here