JMS Serializer: How to limit the depth of serialisation for an object graph

concept picture concept · Mar 23, 2014 · Viewed 11.1k times · Source

Maybe it is just my misunderstanding of this annotation however it does not seam to work as expected.

I have the following object graph

User
 -> Company
  -> Users
   -> Groups
    -> Permissions

As you can see there will be some recursion. JMS handles this quite well by not serialising the other user's company properties as well as not the current user.

However I want the serialization to stop at and include company.

I have tried this expecting that once the level $context->level = 2 it would stop

<?php
namespace FinalConcept\TimeTracker\EntitiesBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * FinalConcept\TimeTracker\EntitiesBundle\Entity
 *
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="FinalConcept\TimeTracker\EntitiesBundle\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable
{
     /**
     * @ORM\ManyToOne(targetEntity="company", inversedBy="users")
     * @ORM\JoinColumn(name="company_id", referencedColumnName="id")
     * @JMS\MaxDepth(depth=1)
     */
    private $company;
}

However this is not the case. Even stepping through the code has not shed any light on how to stop this.

I am happy to create a custom handler if I can only invoke it for a specific path i.e. User.Company

I also need this for User.Groups which has the following graph

User
 -> Groups
  -> Permissions
 -> Users
   -> Groups
     -> users ....

Thanks in advance for any help how to limit the depth of serialization for an object graph

Answer

Alexandru Cosoi picture Alexandru Cosoi · May 19, 2014

Because I did not have access to the latest version of the serializer I had to find a workaround to the @MaxDepth. This may also help you.

Use @JMS\ExclusionPolicy("all") on all entities that are connected.

Now use @JMS\Expose only on those properties that you want to have serialize. On join relations only use this annotation in one direction. That will fix your problem.

namespace FinalConcept\TimeTracker\EntitiesBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * FinalConcept\TimeTracker\EntitiesBundle\Entity
 *
 * @JMS\ExclusionPolicy("all")
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="FinalConcept\TimeTracker\EntitiesBundle\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable
{
     /**
     * @JMS\Expose
     * @ORM\ManyToOne(targetEntity="company", inversedBy="users")
     * @ORM\JoinColumn(name="company_id", referencedColumnName="id")
     */
    private $company;
}