Search code examples
symfonyjmsserializerbundlejms-serializer

Pre_deserialize callback not working in JMSSerializer


I am trying to just execute my Document's __constructor on pre_deserialization via jmsserializer but I don't have a clue why it is not working.

I am loading the serializer metadata from a yaml file looking like this:

AppBundle\Document\Campaign:
exclusion_policy: ALL
xml_root_name: campaign
properties:
    id:
        type: string
        expose: true
    slug:
        type: string
        expose: true
    name:
        type: string
        expose: true
callback_methods:
    pre_deserialize: [__construct]

When I try to deserialize executing:

$object = $serializer->deserialize($jsonString, 'AppBundle\\Document\\Campaign', 'json');

I am unable to reach the contructor function, however If I change the event to any of the others available (pre_serialize, post_serialize and post_deserialize) I do.

I think there are missing code about the handling of this specific event but trying to copy the same code affecting the other events it still not working. It looks like it is never registered in the event dispatcher or something similar.

My environment is:

symfony                2.6.3
jms/serializer         0.16.0
jms/serializer-bundle  0.13.0

Thanks.


Solution

  • I can verify this appears to be a bug in JMS Serializer. For some reason, the service container is not reading the pre_deserialize events and registering it with JMS.

    You can, however, work around this using an event subscriber.

    First define the Subscriber class, similar to your listener:

    <?php
    
    namespace Acme\AcmeBundle\Listener;
    
    use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
    use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
    
    class SerializationSubscriber implements EventSubscriberInterface
    {
    
        /**
         * @inheritdoc
         */
        static public function getSubscribedEvents()
        {
            return array(
                array('event' => 'serializer.pre_deserialize', 'method' => 'onPreDeserialize'),
            );
        }
    
        public function onPreDeserialize(PreDeserializeEvent $event)
        {
            echo "we're about to de-cerealizing";
        }
    }
    

    Then register the Subscriber in your bundle's services configuration:

    parameters:
        acme.serializer_subscriber.class: Acme\AcmeBundle\Listener\SerializationSubscriber
    
    services:
        acme.serializer.subscriber:
        class: %acme.serializer_subscriber.class%
        tags:
            - { name: jms_serializer.event_subscriber }
    

    Rebuild your cache, and you should be good!

    Official Documentation: http://jmsyst.com/libs/serializer/master/event_system