Задонатить и смотреть →
Открой безлимитный доступ к 100+ полезных скринкастов и получай скидки на все предстоящие мероприятия

Сериализация с Serializer

Команды в контроллерах мы до сих пор заполняли данными из JSON-запросов вручную. Это неудобно. И любое несоответствие типов приведёт к ошибке 500 Server Error.

Вместо этого упростим себе работу и автоматизируем ввод и вывод JSON для наших запросов и команд с помощью компонента Serializer. И сделаем красивый вывод списка ошибок типов при неверных запросах:

  • 00:00:23 - Ручное заполнение полей
  • 00:04:06 - Использование сериалайзеров
  • 00:05:10 - Пакет Symfony Serializer
  • 00:10:45 - Установка компонента
  • 00:11:02 - Использование в контроллерах
  • 00:13:33 - Регистрация в DI-контейнере
  • 00:16:05 - Дополнительные нормализаторы
  • 00:18:34 - Пользовательские нормалайзеры
  • 00:19:59 - Внутреннее устройство
  • 00:23:59 - Нормализация в контроллере
  • 00:26:21 - Проверка типов ввода
  • 00:28:32 - Доработка ClearEmptyInputMiddleware
  • 00:30:37 - Возврат 400 Bad Request
  • 00:31:44 - Единообразие с ошибками валидации
  • 00:33:55 - Вывод нескольких ошибок
  • 00:36:14 - Преобразование в исключение валидации
  • 00:38:42 - Вынос обработчиков в Middleware
  • 00:43:03 - Одиночные и множественные
  • 00:45:49 - Контроль наличия полей
  • 00:52:37 - Рефакторинг Middleware
  • 00:54:26 - Создание адаптеров
  • 00:58:23 - Типизация с Generics
  • 01:00:58 - Заполнение через конструктор
  • 01:02:23 - Адаптер для Serializer
  • 01:04:18 - Риски использования при выводе
  • 01:06:17 - Кастомизация ответа
  • 01:11:17 - Проверка результата
Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (11)
Максим

Ура! Подходим стремительными темпами ближе к домену. Выходы стали чаще! Супер! Так держать))

Ответить
Руслан

Спасибо!

Ответить
Владимир Перепеченко

Благодарю за детальность, Дмитрий!

Для меня очень своевременно, так как я сам набрел на Symfony Serializer за три дня до выхода эпизода.

Традиционный вопрос чайника:

Вы сконфигурировали сериалайзер для десиарилизации (объект->string) используя несколько отдельных нормализаторов:

  • DateTimeNormalizer
  • PropertyNormalizer
return new Serializer([
    ...$normalizers,
    new DateTimeNormalizer(),
    new PropertyNormalizer(
        classMetadataFactory: new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())),
        propertyTypeExtractor: new PropertyInfoExtractor(
            typeExtractors: [
                new PhpDocExtractor(),
                new ReflectionExtractor(),
            ]
        )
    ),
    new ArrayDenormalizer(),
], [
    new JsonEncoder(),
]);

и создали непонятные для меня вспомогательные классы Denormalizer, Normalizer.

А так как в моем проекте я собираюсь десереализовывать DTO классы как со свойствами, так и с геттерами/сеттерами, то одного PropertyNormalizer будет недостаточно.

Поэтому вместо набора частных нормалайзеров, я объектов я использовал (больше интуитивно) один могучий объект ObjectNormalizer:

MyObjectSerializer::class => static function (): Serializer {
    $normalizers = [
        new ObjectNormalizer(
            null,
            null,
            null,
            new ReflectionExtractor()
        )
    ];

    $encoders = new JsonEncoder();

    return new Serializer([
        ...$normalizers,
        // new GetSetMethodNormalizer(), 
        new ArrayDenormalizer(),
    ], [
        $encoders
    ]);
},

И свое дело он делает: преобразует json в мой кастомный DTO объект. Причем рекурсивно десериализует сложные вложенные объекты из json во вложенные DTO объекты ( У меня сложная форма с данными из разных таблиц и модулей)

Исходя из этого, мучаюсь вопросами:

1) Для описанного выше функционала (десериализация сложных структур в сложные объекты) , есть ли равенство в использовании сериалайзера собранного

из моего набора: ObjectNormalizer + ReflectionExtractor

и

из Вашго набора: PropertyNormalizer + ArrayDenormalizer + для моего функционала, видимо, придется добавить GetSetMethodNormalizer

На взгляд чайника - мой вариант лаконичнее.

2) также, пока не могу придумать практического применения для массивов, которые Вы используете как временные промежуточные объекты между строками и объектами в процессах serialize/deserialize. Ведь навскидку проще реализовать основную задачу (преобразовывать данные json->object/object->json) напрямую, используя ObjectNormalizer без массивов посредников.

В чём мои заблуждения?

Желаю процветать и здравствовать!

Ответить
Дмитрий Елисеев

есть ли равенство в использовании сериалайзера собранного из моего набора и вашего набора

Да, если нужны геттеры и сеттеры, тогда лучше взять ObjectNormalizer.
Если не нужны, то тогда использовать PropertyNormalizer.

Ответить
Дмитрий Елисеев

Проще реализовать основную задачу (преобразовывать данные json->object/object->json) напрямую.

Поэтому в видео и показаны оба варианта, что можно так и так.

Ответить
Владимир Перепеченко

Дмитрий, с Вашей конфигурацией сериалайзера, моя десериализация прошла - как задумано. Значит мой с ObjectNormalizer просто неверно сконфигурирован.

Ответить
Arunas

спасибо

Ответить
Dzianis

Спасибо, Дмитрий.

Вот я и добрался до 72-го видео. Всё, очень подробно, супер!

Есть понимание когда будут опубликованы следующие видео?

Ответить
Дмитрий

Можно пойти дальше. Экшены принимают сразу в параметрах команды и возвращают объекты. Тогда будет меньше болерплейт кода в экшенах.

Ответить
Андрей

Я бы предложил дтошки респонсов реквестов генерить через свагер, а для очереди использовать протобаф описание. Спасибо за ролик как всегда почерпнул для себя какие то нюансы.

Ответить
Дмитрий Елисеев

Да, если сначала придумывают схему API, то удобнее сделать файл со схемой и по нему генерировать DTO для бэкенда и фронтенда.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Google
GitHub
Yandex
MailRu