Format input and output fields with JMSSerializer (handle single property)

此生再无相见时 提交于 2019-12-05 12:16:09

I finally found the answer.

First I had to create an event subsciber like this :

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;

class TaskSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            [
                'event' => Events::PRE_SERIALIZE,
                'format' => 'json',
                'class' => 'Task', // fully qualified name here
                'method' => 'onPreSerializeTaskJson',
            ],
            [
                'event' => Events::PRE_DESERIALIZE,
                'format' => 'json',
                'class' => 'Task',
                'method' => 'onPreDeserializeTaskJson',
            ]
        ];
    }

    public function onPreSerializeTaskJson(PreSerializeEvent $event)
    {
        /** @var Task $task */
        $task = $event->getObject();

        $task->setStatus($task->getStatusLabel());
    }

    public function onPreDeserializeTaskJson(PreDeserializeEvent $event)
    {
        $data = $event->getData();

        $data['status'] = Task::getStatusFromLabel($data['status']);

        $event->setData($data);
    }
}

What I'm doing here :

  • Before serialization, I set the status value of my Task object with the label
  • Before deserialization, I change the value of the serialized object from the label to the raw integer value

For this solution, field has to be exposed (expose: true or @Expose) to the serializer.

Then I declared the subscriber as a service in Symfony with the tag jms_serializer.event_subscriber.

serializer.subscriber.task:
    class: %serializer.subscriber.task.class% # TaskSubscriber class path
    tags:
        - { name: jms_serializer.event_subscriber }

And it works.

It's the best way I found to both serialize and deserialize. It's also possible to manipulate data on post_serialize and post_deserialize events. For example, add a new field on a serialized object :

use JMS\Serializer\EventDispatcher\ObjectEvent;

public function onPostSerializeTaskJson(ObjectEvent $event)
{
    /** @var Task $task */
    $task = $event->getObject();

    $event->getVisitor()->addData('nb_related', count($task->getRelatedTasks()));
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!