Ошибка при попытке добавить дополнительные данные в ответ ресурса

Я пытаюсь добавить некоторые дополнительные данные к конкретному ресурсу, поэтому я следовал документации, касающейся Декорирование сериализатора и добавление дополнительных данных но когда я протестировал ресурс, я получил эту ошибку:

Вызов функции-члена normalize () для null в (…) / vendor / api-platform / core / src / Serializer / AbstractItemNormalizer.php, строка 426.

Я боролся с этой ошибкой почти два дня, и я не знаю, упускаю ли я какие-то детали или это неправильный способ добавления дополнительных данных в ресурс.
Это мое определение ресурса:

AppBundle\Entity\MediaGenerator\Teaser:
attributes:
access_control: "is_granted('ROLE_ADMIN')"normalization_context:
groups: ['teaser','teaser-read']
denormalization_context:
groups: ['teaser','teaser-write']
order:
position: 'ASC'

Вот мой пользовательский нормализатор:

class ApiNormalizer implements NormalizerInterface
{
private $normalizer;

public function __construct(NormalizerInterface $normalizer)
{
$this->normalizer = $normalizer;
}

public function supportsNormalization($data, $format = null)
{
return $data instanceof Teaser;
}

public function normalize($object, $format = null, array $context = [])
{
$data = $this->normalizer->normalize($object, $format, $context);
if (is_array($data)) {
$data['view'] = "SOME TRANSFORMATION ON TEASER VIEW";
}
return $data;
}

public function supportsDenormalization($data, $type, $format = null)
{
return $this->normalizer->supportsNormalization($data, $type, $format);
}

public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->normalizer->denormalise($data, $class, $format, $context);
}
}

А вот моя декларация services.yml:

AppBundle\Serializer\ApiNormalizer:
decorates: 'api_platform.jsonld.normalizer.item'
arguments: [ '@AppBundle\Serializer\ApiNormalizer.inner' ]
autoconfigure: false

Все остальное работает как шарм, сериализатор в config.yml включен как { enable_annotations: true },

Какие-нибудь проблемы?

Заранее спасибо и отличная работа с ApiPlatform!

1

Решение

https://symfony.com/doc/current/serializer.html

# app/config/config.yml
framework:
# ...
serializer:
name_converter: 'serializer.name_converter.camel_case_to_snake_case'

Беда введенных зависимостей

То, с чем вы сталкиваетесь здесь, это отсутствующая введенная зависимость. Главным образом потому, что вызываемый вами метод не выполняет такую ​​же проверку зависимостей кода где-либо еще. В частности:

// $this->serializer is NULL
return $this->serializer->normalize($attributeValue, $format, $context);

Вы заметите в Normalizer/AbstractObjectNormalizer.php::normalize:

if (!$this->serializer instanceof NormalizerInterface) {
throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer', $attribute));
}

AbstractItemNormalizer::getAttributeValue не имеет этой проверки (и действительно должен.

Быстрая проверка базового сериализатора показывает, что он должен быть определен как SerilaizerAwareTrait:

Это означает, что каждый Serializer предназначен для внедрения зависимостей в каждый нормализатор, использующий его, через шаблон, похожий на инверсию зависимостей (где сам объект вызывает родительский установщик для установки самого себя:

class Serializer {

public function __construct($normalizer) {
$normalizer->setSerializer($this);
}

Все это сводится к паре требований:

  1. Сериализатор ДОЛЖЕН быть создан с введенным нормализатором.
  2. Ваш нормализатор должен быть в этом списке инъекций.

Все это можно увидеть более четко в Symfony Serializer Contstructor

Внимательно посмотрите на Документация по компонентам Sierlizer от Symfony. Сделав небольшую корректировку для их первого примера, вы сможете инициализировать все так, как правильно назначен ваш ApiNormalizer :: serilizer.

$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ApiNormalizer());

$serializer = new Serializer($normalizers, $encoders);
1

Другие решения

Других решений пока нет …