Normalizer / Denormalizer

(De)normalizers are powerful services that transforms the data without encoding/decoding them. For example, supposing your entity has a date/time field. In this case, you don’t need to create a custom mapping for :phpclass:`\DateTime` class to define how to configure such data type. Instead, all you need is to create your custom (de)normalizers:

// src/Serializer/DateTimeNormalizer.php
namespace App\Serializer;

use TSantos\Serializer\Normalizer\DenormalizerInterface;
use TSantos\Serializer\Normalizer\NormalizerInterface;
use TSantos\Serializer\DeserializationContext;
use TSantos\Serializer\SerializationContext;

class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
{
    private $format;

    public function __construct(string $format = \DateTime::ATOM)
    {
        $this->format = $format;
    }

    public function normalize($data, SerializationContext $context)
    {
        if (!$data instanceof \DateTimeInterface) {
            throw new InvalidArgumentException('Data should be instance of ' . \DateTimeInterface::class);
        }

        return $data->format($this->format);
    }

    public function supportsNormalization($data, SerializationContext $context): bool
    {
        return $data instanceof \DateTimeInterface;
    }

    public function denormalize($data, DeserializationContext $context)
    {
        return \DateTime::createFromFormat($this->format, $data);
    }

    public function supportsDenormalization(string $type, $data, DeserializationContext $context): bool
    {
        return $type === \DateTime::class || $type === \DateTimeInterface::class;
    }
}

This bundle automatically recognize services that implements :class:`Normalizer\\NormalizerInterface` and :class:`Normalizer\\DenormalizeInterface` and tag them with the proper tag name.

See also

Please, refer to TSantos Serializer Library repository for a detailed documentation about the normalization process and the built-in normalizers.

Note

If you are using a Symfony version prior to 3.3, you’ll need to register and tag the normalizer services manually.

services:
    App\Serializer\UserNormalizer:
        tags:
            - { name: "tsantos_serializer.normalizer"}
            - { name: "tsantos_serializer.denormalizer"}

Tip

You can use normalizers to transform read-only entities and avoid unnecessary over-head due the serialization process:

// src/Serializer/UserNormalizer.php
namespace App\Serializer;

use App\Entity\User;
use App\Repository\UserRepository;
use TSantos\Serializer\Normalizer\DenormalizerInterface;
use TSantos\Serializer\Normalizer\NormalizerInterface;

class UserNormalizer implements NormalizerInterface, DenormalizerInterface
{
    private $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function normalize($data, SerializationContext $context)
    {
        return $data->getId();
    }

    public function supportsNormalization($data, SerializationContext $context): bool
    {
        return $data instanceof User;
    }

    public function denormalize($data, DeserializationContext $context)
    {
        return $this->userRepository->find($data);
    }

    public function supportsDenormalization(string $type, $data, DeserializationContext $context): bool
    {
        return $type === User::class;
    }
}