Nuevo en Symfony 4.1: Serializar y deserializar clases abstractas

Cuando se trabaja con objetos que son muy parecidos o comparten muchas propiedades es común usar interfaces o clases abstractas. El problema de las clases que heredan de otras clases abstractas es que el componente Serializer no sabe cómo serializarlas o deserializarlas correctamente.

En Symfony 4.1 hemos mejorado el serializador para soportar esta funcionalidad mediante un "discriminador de clases" ("discriminator class mapping" en inglés). Imagina una aplicación que define una clase CodeRepository abstracta de la que heredan las clases GitHubCodeRepository y BitBucketCodeRepository. El siguiente ejemplo muestra cómo serializar/deserializar objetos de ese tipo cuando se utiliza el componente Serializer de forma independiente:

// ...
 
$discriminator = new ClassDiscriminatorResolver();
// $type es la propiedad que se utiliza para discriminar entre clases
$discriminator->addClassMapping(
    CodeRepository::class,
    new ClassDiscriminatorMapping('type', [
        'github' => GitHubCodeRepository::class,
        'bitbucket' => BitBucketCodeRepository::class,
    ])
);
 
// pasa el discriminador como último argumento del normalizador
$serializer = new Serializer(
    array(new ObjectNormalizer(null, null, null, null, $discriminator)),
    array('json' => new JsonEncoder())
);
 
// al serializar, el discriminador sabe que el valor de la propiedad "type"
// de los objetos de tipo GitHubCodeRepository debe ser: {"type": "github"}
$serialized = $serializer->serialize(new GitHubCodeRepository());
 
// al deserializar utilizando la clase abstracta CodeRepository, el discriminador
// utiliza el valor de "type" para saber que $repository es de tipo GitHubCodeRepository
$repository = $serializer->unserialize($serialized, CodeRepository::class, 'json');

Como siempre, utilizar esta funcionalidad dentro de una aplicación Symfony es mucho más sencillo. Simplemente configura el discriminador en un archivo YAML, XML o incluso en una anotación PHP:

namespace App\Repository;
 
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
 
/**
 * @DiscriminatorMap(typeProperty="type", mapping={
 *    "github"="App\Repository\GitHubCodeRepository",
 *    "bitbucket"="App\Repository\BitBucketCodeRepository"
 * })
 */
interface CodeRepository
{
    // ...
}

Puedes leer más sobre esta funcionalidad en la sección Serializing Interfaces and Abstract Classes de la documentación oficial del componente Serializer.

Esta funcionalidad fue contribuida por Samuel Roze en el pull request #24375.

Fuente: New in Symfony 4.1: Serialize and deserialize from abstract classes

Comentarios

Publicada el

19 de febrero de 2018

Etiquetas

Proyectos Symfony destacados

La forma más sencilla de generar el backend de tus aplicaciones Symfony. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.