Сериализация Symfony 4 FOSRestBundle с помощью JMSSerializer

Я создаю API с помощью Symfony 4 и FOSRestBundle. У меня довольно простые отношения:

Сущность: User.php

/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @JMS\Groups({"onlyId"})
     */
    private $id;

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

    //...

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

Сущность: UserProduct.php

/**
* @ORM\Entity(repositoryClass="App\Repository\UserProductRepository")
*/
class UserProduct
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @JMS\Groups({"onlyId"})
     */
    private $id;

    //...

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="userProducts")
     * @JMS\Groups({"onlyId"})
     */
    private $user;

Конфигурация: fos_rest.yaml

fos_rest:
    body_converter:
        enabled: true
    view:
        view_response_listener: 'force'
        formats:
            json: true
    routing_loader:
        default_format: json
#    param_fetcher_listener:  true
#    allowed_methods_listener:  true
#    routing_loader: true
#    view:
#        view_response_listener:  true
#    exception:
#        codes:
#            App\Exception\MyException: 403
#        messages:
#            App\Exception\MyException: Forbidden area.
    format_listener:
        rules:
            - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json, html ] }
            - { path: ^/login_check, stop: true }
            - { path: ^/register, stop: true }

Сначала я не мог POST UserProduct отправлять JSON в конечную точку, когда я отправлял идентификатор пользователя вместе с данными JSON, поскольку он выдавал, что он ожидает экземпляр entity, а не integer или что-то еще, что я отправлял . Я понял это с помощью этого руководства -> https://medium.com/@maartendeboer/using-the-symfony-serializer-with-doctrine-relations-69ecb17e6ebd

он использует сериализатор Symfony. Я получил circular reference ошибку при возврате View из FOSRestBundle. На этом этапе я знал, что circular reference ошибки отлично обрабатываются с помощью инструмента JMS Serializer, и использовал его внутри своего postUserProductAction контроллера:

Чтобы отправить продукт и обработать circular reference, я использую этот контроллер (десериализация отправленного JSON с помощью специального письменного метода десериализации из руководства, его ввод в базу данных и затем возвращение ответа ( not View) с помощью сериализатора JMS и его групп):

class UserProductController extends FOSRestController
    {
    /**
     * @Rest\Route("/api/product", name="userProduct")
     *
     *
     * @Method("POST")
     *
     * @param Request $request
     * @param SerializerInterface $serializer
     * @return Response
     * @throws \InvalidArgumentException
     */
    public function postUserProductAction(Request $request, SerializerInterface $serializer): View
    {
        $userProduct = $serializer->deserialize($request->getContent(), UserProduct::class, 'json');
        dump($userProduct);
        $em = $this->getDoctrine()->getManager();
        $em->persist($userProduct);
        $em->flush();

        $userProduct = $this->JMSSerializeWithGroups($userProduct,array('onlyId'));
        return new View($userProduct, Response::HTTP_OK);
    }
}

    /**
     * @param $entity
     * @param array $groupArray
     * @return mixed|string
     */
    public function JMSSerializeWithGroups($entity, Array $groupArray)
    {
        $JMSserializer = SerializerBuilder::create()->build();
        $entity = $JMSserializer->serialize( $entity, 'json', SerializationContext::create()->setGroups($groupArray));
        return $entity;
    }

Ответ, который я получаю, ясен и ясен:

{
    "id": 100,
    "user": {
        "id": 9
    }
}

Но вроде бы много лишних шагов. Кроме того, если я выберу этот подход, мне нужно будет добавить сериализацию JMS самостоятельно к каждому из моих контроллеров (GET, PUT и т. Д.).

Итак, мой вопрос: почему FOSRestBundle не использует JMS по умолчанию для рендеринга View, как сказано в документации (если он установлен и зарегистрирован)? Должен ли я добавить его где-нибудь дополнительно, чтобы FOSRestBundle распознал его? И, может быть, если бы это было так, мне вообще не нужно было бы использовать Symfony Serializer? Я думаю, что могу потеряться во всех обновлениях Symfony 4.

Спасибо!


person Paul Mark    schedule 23.04.2018    source источник


Ответы (1)


Поскольку никаких предложений я не получал, я придерживаюсь того же решения, которое опубликовал. Я оставлю его на случай, если он кому-то понадобится, так как это полностью рабочий пример.

Ваше здоровье

person Paul Mark    schedule 10.05.2018