Symfony 5 Serializer - 如何不公开整个数据库

问题描述

我们使用 Symfony Serializer 将一些 Doctrine 对象转换为 JSON,目标是将它们作为 API 调用的结果提供。

Out 数据模型有大约 30 个类,所有类都以某种方式相互关联,而 Doctrine 模型反映了这一点。因此,从一个实例到其他链接实例的导航很容易。

现在,我们很高兴在向类添加新属性时不需要进行任何更改。但是,情况不同的是添加了新链接,这通常会增加太多信息,因为链接的类也有链接,并且它们有链接和对象数组...

为了限制这一点,我们通常添加忽略的属性:

protected function serialize($e,$ignored = ['user'])
{
    if ($this->container->has('serializer')) {
        $this->serializer = $this->container->get('serializer');
    } else {
        throw new ServiceNotFoundException('Serializer not found');
    }

    return $this->serializer->serialize($e,'json',[
        'ignored_attributes' => $ignored,ObjectNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object) {
            if (method_exists($object,'getUuid')) {
                return $object->getUuid();
            } elseif (method_exists($object,'getId')) {
                return $object->getId();
            } elseif (method_exists($object,'__toString')) {
                return $object->__toString();
            } else {
                return '[Reference to object of type ' . get_class($object) . ']';
            }
        },]);
}

然后:

return new Response($this->serialize(
    [
        'presentation' => $presentation,],[
        'zoomUser','userExcelDownloads','presentationUserTopics','addedBy','user','presentations','sponsorScopes','sponsorPresentations','showroomScope','presentationsForTopic','presentationsForTopics','presentationHistories','showroomTopics','presentation','presentationHistory',]
));

这行得通,但维护很糟糕——当数据库模型发生变化时,API 调用可能会发出更多 MB 的数据,因为必须忽略新属性。没有办法找到这个。

那你是怎么处理的?

一种解决方案可能是限制类似于 CIRCULAR_REFERENCE_HANDLER 的序列化深度,即对于第三级的对象,只需添加 ID 而不是完整的对象。我怎么能建立这个?

解决方法

Symfony 序列化器具有内置的忽略策略 (https://symfony.com/doc/current/components/serializer.html#ignoring-attributes)

您可以直接从模型中忽略该属性。

use Symfony\Component\Serializer\Annotation\Ignore;

class Presentation
{
    /**
     * @Ignore()
     */
    public $zoomUser;


    //...
}

或使用上下文。

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$normalizer = new ObjectNormalizer();
$encoder = new JsonEncoder();

$serializer = new Serializer([$normalizer],[$encoder]);
$serializer->serialize($presentation,'json',[AbstractNormalizer::IGNORED_ATTRIBUTES => ['zoomUser']]);
,

我们切换到 JMS Serializer Bundle,其中设置了最大值。深度非常简单,对我们有很大帮助。

https://jmsyst.com/bundles/JMSSerializerBundle

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...