1

我正在尝试向特定资源添加一些额外的数据,因此我遵循了有关装饰序列化程序和添加额外数据的文档,但是当我测试资源时出现此错误:

调用 (...)/vendor/api-platform/core/src/Serializer/AbstractItemNormalizer.php 中的 null 成员函数 normalize(),第 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 的出色工作!

4

1 回答 1

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没有这个检查(确实应该。

规范化器需要调用setSerializer

对基本序列化程序的快速检查表明它被定义为SerilaizerAwareTrait

这意味着每个 Serializer 都旨在通过类似于依赖反转的模式将依赖注入到每个使用它的规范化器中(其中对象本身调用父 setter 来设置自己:

class Serializer {

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

这一切归结为几个要求:

  1. 必须使用注入的规范化器来实例化序列化器。
  2. 您的规范化剂需要在该注射列表中。

这一切都可以在Symfony 序列化器构造器中更清楚地看到

下一步去哪里?

仔细查看Symfony 的 Sierlizer 组件文档。通过对他们的第一个示例进行小的调整,您应该能够以正确分配 ApiNormalizer::serilizer 的方式初始化所有内容。

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

$serializer = new Serializer($normalizers, $encoders);
于 2017-10-27T15:09:54.887 回答