symfonysymfony4jmsserializerbundlejms-serializer

Symfony + JMSSerializer throw 500 - handleCircularReference


I'm trying to use the JMSSerializer with Symfony to build a simple json api.

So i have 2 simple Entities (1 User can have many Cars, each Car belongs to one User):

class Car
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="cars")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;
}

class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Car", mappedBy="user", orphanRemoval=true)
     */
    private $cars;
}

Now i want to get all Cars with their User.

My Controller:

class CarController extends AbstractController
{
    /**
     * @param CarRepository $carRepository
     *
     * @Route("/", name="car_index", methods="GET")
     *
     * @return Response
     */
    public function index(CarRepository $carRepository)
    {
        $cars = $carRepository->findAll();
        $serializedEntity = $this->container->get('serializer')->serialize($cars, 'json');

        return new Response($serializedEntity);
    }
}

This will throw a 500 error:

A circular reference has been detected when serializing the object of class \"App\Entity\Car\" (configured limit: 1)

Ok, sounds clear. JMS is trying to get each car with the user, and go to the cars and user ....

So my question is: How to prevent this behaviour? I just want all cars with their user, and after this, the iteration should be stopped.


Solution

  • You need to add max depth checks to prevent circular references. This can be found in the documentation here

    Basically you add the @MaxDepth(1) annotation or configure max_depth if you're using XML/YML configuration. Then serialize like this:

    use JMS\Serializer\SerializationContext;
    
    $serializer->serialize(
        $data,
        'json',
        SerializationContext::create()->enableMaxDepthChecks()
    );
    

    Example Car class with MaxDepth annotation:

    class Car
    {
        /** 
         * @\JMS\Serializer\Annotation\MaxDepth(1)
         *
         * [..]
         */
         private $user;