Я пытаюсь добавить некоторые дополнительные данные к конкретному ресурсу, поэтому я следовал документации, касающейся Декорирование сериализатора и добавление дополнительных данных но когда я протестировал ресурс, я получил эту ошибку:
Вызов функции-члена 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!
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);
}
Все это сводится к паре требований:
Все это можно увидеть более четко в Symfony Serializer Contstructor
Внимательно посмотрите на Документация по компонентам Sierlizer от Symfony. Сделав небольшую корректировку для их первого примера, вы сможете инициализировать все так, как правильно назначен ваш ApiNormalizer :: serilizer.
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ApiNormalizer());
$serializer = new Serializer($normalizers, $encoders);
Других решений пока нет …