serializationsymfonyjmsserializerbundle

Add extra fields using JMS Serializer bundle


I've an entity I usually serialize using the JMS Serializer bundle. I have to add to the serialization some fields that doesn't reside in the entity itself but are gathered with some db queries.

My idea was to create a custom object, fill the fields with the entity fields and add the custom one. But this seems a bit tricky and expensive to do for every variation (I use lot of serialization groups) of the class.

Is there a better/standard way to do this? Using a factory? Pre/Post serialization events?

Maybe I can listen for the serialization and checking entity type and serialization groups add the custom fields? But instead of making a query for each entity it would be better to gather all the data of the related entities and then add it to them. Any help is appreciated


Solution

  • I've found the solution by myself,

    to add a custom field after the serialization has been done we've to create a listener class like this:

    <?php
    
    namespace Acme\DemoBundle\Listener;
    
    use JMS\DiExtraBundle\Annotation\Service;
    use JMS\DiExtraBundle\Annotation\Tag;
    use JMS\DiExtraBundle\Annotation\Inject;
    use JMS\DiExtraBundle\Annotation\InjectParams;
    use Symfony\Component\HttpKernel\Event\PostResponseEvent;
    use Acme\DemoBundle\Entity\Team;
    use JMS\Serializer\Handler\SubscribingHandlerInterface;
    use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
    use JMS\Serializer\EventDispatcher\PreSerializeEvent;
    use JMS\Serializer\EventDispatcher\ObjectEvent;
    use JMS\Serializer\GraphNavigator;
    use JMS\Serializer\JsonSerializationVisitor;
    
    /**
     * Add data after serialization
     *
     * @Service("acme.listener.serializationlistener")
     * @Tag("jms_serializer.event_subscriber")
     */
    class SerializationListener implements EventSubscriberInterface
    {
    
        /**
         * @inheritdoc
         */
        static public function getSubscribedEvents()
        {
            return array(
                array('event' => 'serializer.post_serialize', 'class' => 'Acme\DemoBundle\Entity\Team', 'method' => 'onPostSerialize'),
            );
        }
    
        public function onPostSerialize(ObjectEvent $event)
        {
            $event->getVisitor()->addData('someKey','someValue');
        }
    }
    

    That way you can add data to the serialized element.

    Instead, if you want to edit an object just before serialization use the pre_serialize event, be aware that you need to already have a variable (and the correct serialization groups) if you want to use pre_serialize for adding a value.