Как работать с кастомной сериализацией/нормализацией?

В Symfony можно настроить кастомную сериализацию и нормализацию данных при работе с API. Это может быть полезно, когда вам нужно изменить структуру или формат вывода данных, а также добавить дополнительную логику обработки.

Symfony предлагает два основных подхода к настройке кастомной сериализации/нормализации: с использованием аннотаций или с использованием конфигурации в файле сериализации.

1. Аннотации:
Сериализацию/нормализацию можно настроить с использованием аннотаций прямо в классе. Класс должен быть аннотирован с помощью @SerializerSerializedName и @SerializerGroups, чтобы определить имена полей и группы сериализации.

use SymfonyComponentSerializerAnnotationSerializedName;
use SymfonyComponentSerializerAnnotationGroups;

class User
{
    /**
     * @SerializedName("firstName")
     * @Groups({"api"})
     */
    private $firstName;

    /**
     * @SerializedName("lastName")
     * @Groups({"api"})
     */
    private $lastName;

    ...

    // Геттеры и сеттеры

}

В контроллере вы можете использовать аннотацию @Groups для указания группы сериализации:

use SymfonyComponentSerializerAnnotationGroups;

class UserController extends AbstractController
{
    ...

    /**
     * @Groups({"api"})
     */
    public function show(User $user, SerializerInterface $serializer)
    {
        $data = $serializer->serialize($user, 'json');

        ...
    }
    
    ...

}

2. Конфигурация в файле сериализации:
Если вы предпочитаете не использовать аннотации в классе, то вы можете настроить сериализацию/нормализацию в файле конфигурации, например, в формате YAML или XML.

# config/packages/serializer.yaml

framework:
    serializer:
        mapping:
            paths:
                - '%kernel.project_dir%/src/Entity'
        # Настройки сериализации/нормализации
        ...
// src/Entity/User.php

namespace AppEntity;

class User
{
    private $firstName;

    private $lastName;

    ...

    // Геттеры и сеттеры

}

Вы также можете определить кастомные нормализаторы и сериализаторы, настроить кастомные свойства или использовать события сериализации/нормализации для выполнения определенных операций до или после процесса.

Например, чтобы настроить кастомную сериализацию/нормализацию с помощью событий, вы можете создать сервис, реализующий интерфейс EventSubscriberInterface:

use SymfonyComponentSerializerEventDispatcherEventSubscriberInterface;
use SymfonyComponentSerializerEventDispatcherEvents;
use SymfonyComponentSerializerEventDispatcherEventSubscriberTrait;
use SymfonyComponentSerializerEventDispatcherPreSerializeEvent;

class UserSerializerSubscriber implements EventSubscriberInterface
{
    use EventSubscriberTrait;

    public function onPreSerialize(PreSerializeEvent $event)
    {
        $object = $event->getObject();
        $data = $event->getData();

        // Ваша логика сериализации/нормализации

        $event->setData($data);
    }

    public static function getSubscribedEvents()
    {
        return [
            Events::PRE_SERIALIZE => 'onPreSerialize',
        ];
    }
}

Затем зарегистрируйте этот сервис в файле services.yaml:

# config/services.yaml

services:
    AppSubscriberUserSerializerSubscriber:
        tags:
            - { name: serializer.event_subscriber }

В этом примере событие PRE_SERIALIZE запускается перед началом сериализации/нормализации, и вы можете внести любые изменения в данные.

В итоге, для реализации кастомной сериализации/нормализации данных в Symfony, вы можете использовать аннотации в классе, конфигурационные файлы, кастомные нормализаторы/сериализаторы либо события сериализации/нормализации. Выбор подхода зависит от требований вашей системы и предпочтений.