Why does my response return "blank" when I set the setCircularReferenceHandler
callback?
EDIT:
Would appear that it returns nothing, but does set the header to 500 Internal Server Error
. This is confusing as Symfony should send some kind of error response concerning the error?
I wrapped $json = $serializer->serialize($data, 'json');
in a try/catch but no explicit error is thrown so nothing is caught. Any ideas would be really helpful.
When querying for an Entity Media I get a blank response. Entity Media is mapped (with Doctrine) to Entity Author. As they are linked, indefinite loops can occur when trying to serialize.
I had hoped that using the Circular Reference Handler I could avoid just that, but it's not working.
This is the error I'm getting when I'm NOT setting the Circular Reference Handler:
A circular reference has been detected when serializing the object of class "Proxies__CG__\AppBundle\Entity\Author\Author" (configured limit: 1) (500 Internal Server Error)
Now this error is completely expected, as my Entity Author points back to the Entity Media when originally querying for a Media ( 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();
})
];
}
}
My Entities implement JsonSerializable
interface so I define what attributes are returned (Which is what JsonSerializeNormalizer
requires). This works completely when I remove the "medias" property in the Author's class, everything works.
Here is how I use my serliazer with my normalizer.
/**
* @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
I tried to reproduce your error, and for me everything worked as expected (see code samples below).
So, your setCircularReferenceHandler() works fine.
Maybe try to run my code, and update it with your real entities and data sources step by step, until you see what causes the error.
Test (instead of your controller):
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));
}
}
Media entity
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
}
Author entity
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With