Как создать ваш пользовательский нормализатор
Дата обновления перевода 2024-07-27
Как создать ваш пользовательский нормализатор
Компонент Serializer использует нормализаторы, чтобы проеобразовать любые данные в массив. Компонент предоставляет несколько встроенных нормализаторов, но вам может понадобиться создать собственный нормализатор, чтобы преобразовать неподдерживаемую структуру данных.
Создание нового нормализатора
Представьте, что вы хотите добавить, изменить или удалить некоторые свойства во
время процесса сериализации. Для этого вам нужно будет создать собственный нормализатор.
Но обычно предпочтительно позволить Symfony нормализовать объект, затем подключиться
к нормализации, чтобы настроить нормализованные данные. Для этого вы можете внедрить
NormalizerInterface
и подключить его к нормализатору объектов Symfony. Это даст
доступ к свойству $normalizer
, которое берет на себя большую часть
процесса нормализации:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// src/Serializer/TopicNormalizer.php
namespace App\Serializer;
use App\Entity\Topic;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class TopicNormalizer implements NormalizerInterface
{
public function __construct(
#[Autowire(service: 'serializer.normalizer.object')]
private readonly NormalizerInterface $normalizer,
private UrlGeneratorInterface $router,
) {
}
public function normalize($topic, string $format = null, array $context = []): array
{
$data = $this->normalizer->normalize($topic, $format, $context);
// Здесь, добавьте, измените или удалите некоторые данные:
$data['href']['self'] = $this->router->generate('topic_show', [
'id' => $topic->getId(),
], UrlGeneratorInterface::ABSOLUTE_URL);
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return $data instanceof Topic;
}
public function getSupportedTypes(?string $format): array
{
return [
Topic::class => true,
];
}
}
Регистрация в вашем приложении
Перед использованием этого нормализатора в приложении Symfony, он должен быть
зарегитрирован в качестве сервиса и тегирован с
помощью serializer.normalizer
. Если вы используете
конфигурацию services.yaml по умолчанию ,
это делается автоматически!
Производительность нормализаторов/денормализаторов
Чтобы понять, какой нормализатор (или денормализатор) должен быть использован для обработки объекта, класс Serializer циклично вызовет supportsNormalization() (или supportsDenormalization()) из всех зарегистрированных нормализаторов (или денормализаторов).
Кроме того, и
NormalizerInterface,
и DenormalizerInterface
содержат метод getSupportedTypes()
. Этот метод позволяет нормализаторам или
денормализаторам объявить тип объектов, с которыми они могут работать, и определить,
можно ли их кешировать. Имея эту информацию, даже если вызов supports*()
не
является кешируемым, Serializer может пропустить тонну вызовов метода supports*()
,
в некоторых случаях существенно повышая производительность.
Метод getSupportedTypes()
должен возвращать массив, в котором ключи
представляют собой поддерживаемые типы, а значения указывают, является ли результат
вызова метода supports*()
кешируемым. Формат возвращаемого массива выглядит следующим
образом:
- Специальный ключ
object
может быть использован для указания того, что нормализатор или денормализатор поддерживает какие-либо классы или интерфейсы. - Специальный ключ
*
может быть использован для указания на то, что нормализатор или денормализатор может поддерживать любые типы. - Остальные ключи в массиве должны соответствовать конкретным типам, которые поддерживает нормализатор или денормализатор.
- Значения, связанные с каждым типом, должны быть булевыми, указывающими, поддерживает ли
результат вызова метода
supports*()
для этого типа кеширование.
Значениеtrue
означает, что результат можно кешировать, аfalse
означает, что результат не может быть кеширован. - Значение
null
для типа означает, что нормализатор или денормализатор не поддерживает этот тип.
Вот пример использования метода getSupportedTypes()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class MyNormalizer implements NormalizerInterface
{
// ...
public function getSupportedTypes(?string $format): array
{
return [
'object' => null, // Не поддерживает никаких классов или интерфейсов
'*' => false, // Поддерживает любые другие типы, но результат нельзя кешировать
MyCustomClass::class => true, // Поддерживает MyCustomClass и результат можно кешировать
];
}
}
Note
Реализации метода supports*()
не должны предполагать, что
getSupportedTypes()
был вызван ранее.