Search code examples
symfonydoctrine-ormjmsserializerbundlejms-serializer

Empty relations when serializing with JMSSerializer


I am having troubles while writing a controller-action inside a Symfony project, that should return data (in this particular case orders of a web-shop). Yeah ... It's a kind of a REST-API. That route just get's called from some JavaScript. And the data has to be visualized on the client-side.

The Problem:

I cannot find out, why the serialization of related entities results in empty objects. In this example it is the user of an order, which is empty.

This is a sample output:

orders: [
  {
    id: 2,
    created: '2016-05-04T11:40:27+00:00',
    user: {},
  }
]

When I do something like

$orders = $this->getDoctrine()->getRepository('AppBundle:Order')
  ->findAllCompleted();

$serializationContext->setSerializeNull(true);
$serializationContext->setGroups(['statistics']);

$json = $serializer->serialize($orders, 'json', $serializationContext);
$response = new Response($json, $statusCode, [
  'Content-Type' => 'application/json',
]);

return $response;

... i get a nice JSON response from the server, but every related entity of each order, like let's say user is {} (empty).

Even if I dump the related entity before it gets serialized like so:

[...]
$myOrder = array_filter($orders, function($order) {
  if ($order->getId() == 2) {
    return true;
  }
  return false;
});

dump($myOrder[0]->getUser());
die();

... it results in an empty (unhydrated) entity.

But if I change this debugging code to:

$myOrder = array_filter($orders, function($order) {
  if ($order->getId() == 2) {
    return true;
  }
  return false;
});

dump($myOrder[0]->getUser()->getUsername());
die();

... I get a clear output (string) with the value of the username of that entity.

So I think the issue is about a non hydrated entity, and not the serializer or its wrong configuration.

How can I get the JMSSerializer to take care of the hydration of those related entities?

I didn't find any hint in the docs ...

BTW, this are the JMS entity configs of order and user.

AppBundle\Entity\User:
  exclusion_policy: ALL
  properties:
    userMeta:
      expose: true
    address:
      expose: true
    username:
      expose: true
    email:
      expose: true
    isReseller:
      expose: true
    acceptPublicOrders:
      expose: true
    vatNumber:
      expose: true
    taxRate:
      expose: true


AppBundle\Entity\Order:
  exclusion_policy: NONE
  properties:
    id:
      groups: ['statistics']

    user:
      groups: ['statistics']

    configuration:
      groups: ['statistics']

    created:
      groups: ['statistics']

    invoiceItems:
      groups: ['statistics']
      exclude: true

Solution

  • I think your problem is caused by doctrine lazy loading maybe you can try to change the fetch mode of the User association to EAGER in your Order entity

    @ManyToOne(targetEntity="Cart", cascade={"all"}, fetch="EAGER")

    By default i think it doesn't fetch the associations unless you call it directly like you did here

    dump($myOrder[0]->getUser()->getUsername());

    https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-onetoone

    Or this if you use DQL
    14.7.6.6. Temporarily change fetch mode in DQL

    http://doctrine-orm.readthedocs.io/en/latest/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql

    Edit : i was wrong I made some tests everything worked fine with lazy loading or eager until i tried with groups, even if the fields are exposed you don't use the Default group so it only take the things with the 'statistics' group on it Try to add the default group here

    $serializationContext->setGroups(['Default','statistics']);

    Or add the statistics group on your user fields both worked for me