В моем недавнем проекте Drupal я использовал пользовательские ресурсы отдыха. В этом пользовательском ресурсе отдыха ответ был создан следующим образом:
$data = [ 'key' => 'value', ]; return new ResourceResponse($data);
который выводится как -
{ "key": "value" }
который выглядел хорошо. Но проблема возникла, когда данные были пусты. В случае пустых данных ($data = []) ответ был следующим:
[]
Здесь ответом был пустой массив. Мы можем ясно видеть, что есть разница в ответе, когда данные не пусты и когда данные пусты. В случае непустых данных ответом был объект, а в случае пустых данных — массив. Требование состояло в том, чтобы ответ был последовательным. Это означает, что ответ должен быть объектом, даже если массив данных пуст.
Я просто и очень быстро просто добавил пустой чек вот так -
$data = empty($data)?? new \stdClass(); return new ResourceResponse($data);
и думал, что теперь все будет хорошо, но я получил исключение «Не удалось нормализовать объект типа stdClass, не найден поддерживающий нормализатор»
Symfony\Component\Serializer\Exception\NotNormalizableValueException
Это произошло потому, что тип объекта (stdClass()), который мы пытались нормализовать (преобразовать в массив), не поддерживался системой (Drupal). И, следовательно, на сцену вышел пользовательский нормализатор.
Обратитесь к https://www.drupal.org/docs/8/api/serialization-api/how-the-serializer-works, чтобы узнать больше о нормализаторе.
Чтобы создать собственный нормализатор для поддержки объекта типа stdClass, нам пришлось зарегистрировать помеченный сервис, как показано ниже:
my_custom_module.normalizer_stdclass: class: Drupal\my_custom_module\Normalizer\NormalizerStdClass arguments: ['\stdClass'] tags: - { name: normalizer}
А класс обслуживания выглядел ниже -
<?php namespace Drupal\my_custom_module\Normalizer; use Drupal\serialization\Normalizer\NormalizerBase; /** * StdClass normalizer. */ class NormalizerStdClass extends NormalizerBase { /** * Constructs a NormalizerStdClass object. * * @param string|array $supported_class * The supported class(es). */ public function __construct($supported_class) { $this->supportedInterfaceOrClass = $supported_class; } /** * {@inheritdoc} */ public function normalize($object, $format = NULL, array $context = []) { return new \stdClass(); } }
И тогда код остального ресурса стал -
$data = !empty($data) ?? new \stdClass(); return new ResourceResponse($data);
который был точно таким же, как мы использовали ранее. Но на этот раз он не вернул никаких исключений из-за регистрации новой службы нормализатора для stdClass. На этот раз он просто вернул объект в случае пустого массива, как показано ниже:
{}
что было в соответствии с требованиями, и я также был рад реализовать собственный нормализатор.
Короче говоря, чтобы создать собственный нормализатор, нам просто нужно зарегистрировать и реализовать службу с тегами (с тегом «нормализатор»).