Skip to content

Commit

Permalink
feature #4299 [Serializer] Handle circular references. symfony/symfon…
Browse files Browse the repository at this point in the history
…y#12098. (dunglas)

This PR was merged into the master branch.

Discussion
----------

[Serializer] Handle circular references. symfony/symfony#12098.

| Q             | A
| ------------- | ---
| Doc fix?      | no
| New docs?     | symfony/symfony#12098
| Applies to    | 2.6 or 2.7
| Fixed tickets | n/a

Commits
-------

1a1476e [Serializer] Handle circular references. symfony/symfony#12098.
  • Loading branch information
weaverryan committed Oct 28, 2014
2 parents a58b0d1 + 1a1476e commit bd85865
Showing 1 changed file with 96 additions and 1 deletion.
97 changes: 96 additions & 1 deletion components/serializer.rst
Expand Up @@ -238,14 +238,109 @@ When serializing, you can set a callback to format a specific object property::
$serializer->serialize($person, 'json');
// Output: {"name":"cordoval", "age": 34, "createdAt": "2014-03-22T09:43:12-0500"}

Handling Circular References
----------------------------

.. versionadded:: 2.6
Handling of circular references was introduced in Symfony 2.6. In previous
versions of Symfony, circular references led to infinite loops.

Circular references are common when dealing with entity relations::

class Organization
{
private $name;
private $members;

public function setName($name)
{
$this->name = $name;
}

public function getName()
{
return $this->name;
}

public function setMembers(array $members)
{
$this->members = $members;
}

public function getMembers()
{
return $this->members;
}
}

class Member
{
private $name;
private $organization;

public function setName($name)
{
$this->name = $name;
}

public function getName()
{
return $this->name;
}

public function setOrganization(Organization $organization)
{
$this->organization = $organization;
}

public function getOrganization()
{
return $this->organization;
}
}

To avoid infinite loops, :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer`
throws a :class:`Symfony\\Component\\Serializer\\Exception\\CircularReferenceException`
when such case is encountered::

$member = new Member();
$member->setName('Kévin');

$org = new Organization();
$org->setName('Les-Tilleuls.coop');
$org->setMembers(array($member));

$member->setOrganization($kevin);

echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException

The ``setCircularReferenceLimit()`` method of this normalizer sets the number
of times serializing the same object must occur before considering being
in a circular reference. Its default value is ``1``.

Instead of throwing an exception, circular references can also be handled
by custom callables. This is especially useful when serializing entities
having unique identifiers::

$encoder = new JsonEncoder();
$normalizer = new GetSetMethodNormalizer();

$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getName();
});

$serializer = new Serializer(array($normalizer), array($encoder));
echo $serializer->serialize($org, 'json');
// {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"]}

JMSSerializer
-------------

A popular third-party library, `JMS serializer`_, provides a more
sophisticated albeit more complex solution. This library includes the
ability to configure how your objects should be serialized/deserialized via
annotations (as well as YAML, XML and PHP), integration with the Doctrine ORM,
and handling of other complex cases (e.g. circular references).
and handling of other complex cases.

.. _`JMS serializer`: https://github.com/schmittjoh/serializer
.. _Packagist: https://packagist.org/packages/symfony/serializer

0 comments on commit bd85865

Please sign in to comment.