尝试将额外数据添加到资源响应时出错

时间:2017-10-27 13:39:12

标签: php symfony serialization api-platform.com

我正在尝试向特定资源添加一些额外数据,因此我按照有关Decorating a Serializer and Add Extra Data的文档进行操作,但是当我测试资源时出现此错误:

  

在(...)/ vendor / api-platform / core / src / Serializer / AbstractItemNormalizer.php,第426行调用null上的成员函数normalize()。

我在这个错误中苦苦挣扎了近两天,我不知道我是否遗漏了一些细节,或者这不是向资源添加额外数据的正确方法。 这是我的资源定义:

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 个答案:

答案 0 :(得分: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都应该通过类似于依赖项反转的模式依赖注入到每个使用它的规范化器中(其中对象本身调用父设置器来设置它自己:

class Serializer {

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

这一切归结为几个要求:

  1. 必须使用注入的normalizer [s]实例化一个Serializer。
  2. 您的标准化者需要在该注射列表中。
  3. Symfony Serializer Contstructor

    可以更清楚地看到这一点

    下一步去哪儿?

    仔细查看Symfony's Sierlizer Component Docs。通过对其第一个示例进行小幅调整,您应该能够以正确分配ApiNormalizer :: serilizer的方式初始化所有内容。

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