【问题标题】:Serializer using Normalizer returns nothing when using setCircularReferenceHandler使用 Normalizer 的序列化器在使用 setCircularReferenceHandler 时不返回任何内容
【发布时间】:2017-09-05 15:34:31
【问题描述】:

问题:

当我设置setCircularReferenceHandler 回调时,为什么我的响应返回“空白”?

编辑:

看起来它什么也不返回,但确实将标头设置为500 Internal Server Error。这很令人困惑,因为 Symfony 应该发送某种关于错误的错误响应?

我将 $json = $serializer->serialize($data, 'json'); 包裹在 try/catch 中,但没有抛出显式错误,因此没有捕获任何内容。任何想法都会很有帮助。

上下文:

查询实体媒体时,我得到一个空白响应。实体媒体(使用 Doctrine)映射到实体作者。由于它们是链接在一起的,因此在尝试序列化时可能会出现无限循环。

我曾希望使用循环引用处理程序可以避免这种情况,但它不起作用。

错误:

这是我在设置循环引用处理程序时遇到的错误:

序列化类“Proxies__CG__\AppBundle\Entity\Author\Author”的对象时检测到循环引用(配置限制:1)(500 内部服务器错误)

现在这个错误是完全可以预料到的,因为我的实体作者在最初查询媒体时指向实体媒体 (Media -> Author -> Media)

   class Author implements JsonSerializable {

     //Properties, Getters and setters here

     /**
     * Specify data which should be serialized to JSON
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
     * @return mixed data which can be serialized by <b>json_encode</b>,
     * which is a value of any type other than a resource.
     * @since 5.4.0
     */
    function jsonSerialize()
    {
        return [
            "title"     => $this->getTitle(),
            "id"        => $this->getId(),
            "firstname" => $this->getFirstname(),
            "lastname"  => $this->getLastname(),

            //This is the problem right here. Circular reference.
            "medias"    => $this->getAuthorsMedia()->map(function($object){
                return $object->getMedia();
            })
        ];
    }
  }

我尝试过的:

我的实体实现了JsonSerializable 接口,所以我定义了返回的属性(这是JsonSerializeNormalizer 要求的)。这完全有效当我删除作者类中的“medias”属性时一切正常

这是我如何将我的 serliazer 与我的规范化器一起使用。

/**
 * @Route("/media")
 * Class MediaController
 * @package BackBundle\Controller\Media
 */
class MediaController extends Controller
{

    /**
     * @Route("")
     * @Method({"GET"})
     */
    public function listAction(){
        /** @var MediaService $mediaS */
        $mediaS= $this->get("app.media");

        /** @var array $data */
        $data = $mediaS->getAll();
        $normalizer = new JsonSerializableNormalizer();
        $normalizer->setCircularReferenceLimit(1);
        $normalizer->setCircularReferenceHandler(function($object){
            return $object->getId();
        });
        $serializer = new Serializer([$normalizer], [new JsonEncoder()]);

        $json = $serializer->serialize($data, 'json');

        return new Response($json);
    }

}

Github issue opened

【问题讨论】:

  • 您是否尝试添加元数据并启用enable_max_depth 设置来解决此问题?见“Handling Serialization Depth
  • 你想序列化多少层?
  • enable_max_depth 被任何扩展 AbstractObjectNormalizer 的东西使用。 JsonSerializableNormalizer 直接继承自 AbstractNormalizer,根本不使用该选项。

标签: php symfony doctrine-orm php-7.1 symfony-3.3


【解决方案1】:

我试图重现您的错误,对我来说一切都按预期工作(请参阅下面的代码示例)。

所以,您的 setCircularReferenceHandler() 工作正常

也许尝试运行我的代码,并使用您的真实实体和数据源逐步更新它,直到您看到导致错误的原因。

测试(而不是你的控制器):

class SerializerTest extends \PHPUnit\Framework\TestCase
{
    public function testIndex()
    {
        $media = new Media();
        $author = new Author();

        $media->setAuthor($author);
        $author->addMedia($media);
        $data = [$media];

        $normalizer = new JsonSerializableNormalizer();
        $normalizer->setCircularReferenceLimit(1);
        $normalizer->setCircularReferenceHandler(function($object){
            /** @var Media $object */
            return $object->getId();
        });
        $serializer = new Serializer([$normalizer], [new JsonEncoder()]);

        $json = $serializer->serialize($data, 'json');

        $this->assertJson($json);
        $this->assertCount(1, json_decode($json));
    }
}

媒体实体

class Media implements \JsonSerializable
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Author
     *
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="medias")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    private $author;

    /**
     * {@inheritdoc}
     */
    function jsonSerialize()
    {
        return [
            "id"        => $this->getId(),
            "author"    => $this->getAuthor(),
        ];
    }
    //todo: here getter and setters, generated by doctrine
}

作者实体

class Author implements \JsonSerializable
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Media[]
     *
     * @ORM\OneToMany(targetEntity="Media", mappedBy="author")
     */
    private $medias;

    /**
     * {@inheritdoc}
     */
    function jsonSerialize()
    {
        return [
            "id"        => $this->getId(),
            "medias"    => $this->getMedias(),
        ];
    }
    //todo: here getter and setters, generated by doctrine
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-17
    • 2015-06-11
    • 2018-09-05
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    相关资源
    最近更新 更多