Задонатить и смотреть →
Открыть доступ к сотне полезных скринкастов

Сериализация с 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
Комментарии (7)
Максим

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

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

Спасибо!

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

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

Для меня очень своевременно, так как я сам набрел на 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

спасибо

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

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

Google
GitHub
Yandex
MailRu