Пустые отношения при сериализации с помощью JMSSerializer

У меня возникли проблемы при написании действия контроллера внутри проекта Symfony, которое должно возвращать данные (в данном случае заказы интернет-магазина). Ага... Это своего рода REST-API. Этот маршрут просто вызывается из некоторого JavaScript. И данные должны быть визуализированы на стороне клиента.

Эта проблема:

Я не могу понять, почему сериализация связанных сущностей приводит к пустым объектам. В этом примере это пользователь заказа, который пуст.

Это пример вывода:

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

Когда я делаю что-то вроде

$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;

... я получаю хороший ответ JSON от сервера, но каждый связанный объект каждого заказа, например, скажем, user, является {} (пустым).

Даже если я сброшу связанный объект до того, как он будет сериализован следующим образом:

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

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

... это приводит к пустой (негидратированной) сущности.

Но если я изменю этот код отладки на:

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

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

... Я получаю четкий вывод (строку) со значением имени пользователя этого объекта.

Поэтому я думаю, что проблема связана с негидратированным объектом, а не с сериализатором или его неправильной конфигурацией.

Как я могу заставить JMSSerializer позаботиться о гидратации этих связанных сущностей?

Я не нашел подсказки в документах...

Кстати, это конфигурации объекта JMS порядка и пользователя.

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

person Edgar Alloro    schedule 03.05.2018    source источник
comment
Вы установили exclusion_policy: all на User ?   -  person Weenesta - Mathieu Dormeval    schedule 04.05.2018
comment
да. Но у меня также есть явные директивы expose: true. См. мой обновленный вопрос с соответствующими конфигурациями объектов jms.   -  person Edgar Alloro    schedule 04.05.2018


Ответы (1)


Я думаю, что ваша проблема вызвана ленивой загрузкой доктрины, возможно, вы можете попытаться изменить режим выборки ассоциации пользователя на EAGER в вашем объекте Order

@ManyToOne(targetEntity="Корзина", cascade={"all"}, fetch="EAGER")

По умолчанию я думаю, что он не извлекает ассоциации, если вы не вызываете его напрямую, как вы сделали здесь

дамп($myOrder[0]->getUser()->getUsername());

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

Или это, если вы используете DQL
14.7.6.6. Временно изменить режим выборки в DQL

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

Редактировать: я был неправ, я сделал несколько тестов, все работало нормально с ленивой загрузкой или нетерпеливым, пока я не попробовал с группами, даже если поля открыты, вы не используете группу по умолчанию, поэтому она принимает только вещи с группой «статистика» на Попробуйте добавить сюда группу по умолчанию

$serializationContext->setGroups(['По умолчанию','статистика']);

Или добавьте группу статистики в свои пользовательские поля, и это сработало для меня.

person Jordan    schedule 04.05.2018
comment
Да, я думаю, вы правы. Это связано с ленивой загрузкой. Потому что я контролирую поля, которые сериализуются. Если я устанавливаю некоторые exclude: true в конфигурации yml или через аннотацию, поле user вообще не существует в моем ответе API, и это нормально. Но то, что это NULL, связано с ленивой загрузкой. Я не уверен, приведет ли EAGER к плохой работе с тысячами заказов. Разве нет другого пути? Я не знаю почему, но в других моих конечных точках API нет проблем с сериализацией отношений. Все они заполняются своими значениями... - person Edgar Alloro; 05.05.2018
comment
Хорошо, я думаю, я понял, я сделал несколько тестов, все работало нормально с ленивой загрузкой или с нетерпением, пока я не попробовал с группами, даже если поля открыты, вы не используете группу по умолчанию, поэтому она принимает только вещи со «статистикой». группа на нем Попробуйте добавить сюда группу по умолчанию $serializationContext-›setGroups(['Default','statistics']); Или добавьте группу статистики по нужным вам пользовательским полям У меня оба работали - person Jordan; 05.05.2018
comment
добавление группы «По умолчанию» не является вариантом, потому что в этом контексте ответы получают до 30 МБ json :-) Но добавление группы статистики в определение метаданных — это способ добиться этого. Во всяком случае, это не сработало. Вот почему я удалил JMSSerializerBundle из всего проекта. Просто занимаюсь рефакторингом, поэтому я могу использовать компонент Symfony/Serializer, который отлично справляется со своей задачей прямо сейчас. Мне просто нужно выяснить, как реализовать функцию виртуальной собственности... - person Edgar Alloro; 05.05.2018