Сериализатор с использованием нормализатора ничего не возвращает при использовании setCircularReferenceHandler
Вопрос:
Почему мой ответ возвращает "пустой", когда я устанавливаю обратный вызов setCircularReferenceHandler
?
РЕДАКТИРОВАТЬ:
Может показаться, что он ничего не возвращает, но устанавливает заголовок в 500 Internal Server Error
. Это сбивает с толку, так как Symfony должен отправить какой-то ответ об ошибке, касающийся ошибки?
Я завернул $json = $serializer->serialize($data, 'json');
в try/catch, но явной ошибки не было, поэтому ничего не поймано. Любые идеи были бы действительно полезны.
Контекст:
При запросе на носитель сущности Я получаю пустой ответ. Носитель сущности сопоставляется (с Доктриной) с Автором сущности. Поскольку они связаны, при попытке сериализации могут возникать неопределенные циклы.
Я надеялся, что с помощью обработчика циклических ссылок я смогу избежать именно этого, но это не работает.
Ошибка:
Это ошибка, которую я получаю, когда я НЕ устанавливаю обработчик циклических ссылок:
При сериализации была обнаружена циклическая ссылка объект класса "Прокси__CG__\AppBundle\Сущность\Автор\Автор" (настроенное ограничение: 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
). Это работает полностью когда я удалите свойство "медиас" в классе Автора, все работает.
Вот как я использую свой серлиазер с моим нормализатором.
/**
* @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);
}
}
1 answers
Я попытался воспроизвести вашу ошибку, и для меня все работало так, как ожидалось (см. Примеры кода ниже).
Итак, ваш 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
}