Як створити ваш користувацький нормалізатор
Дата оновлення перекладу 2024-06-03
Як створити ваш користувацький нормалізатор
Компонент 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
// 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['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()
викликався раніше.