В моем недавнем проекте 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. На этот раз он просто вернул объект в случае пустого массива, как показано ниже:

{}

что было в соответствии с требованиями, и я также был рад реализовать собственный нормализатор.

Короче говоря, чтобы создать собственный нормализатор, нам просто нужно зарегистрировать и реализовать службу с тегами (с тегом «нормализатор»).

Ссылка: