Outils pour utilisateurs

Outils du site


how_to_overwrite_the_default_handler_jmsserializer

How to overwrite the default handler in JMSSerializer

Context

During a personal project, I used Symfony to consume an API built for a Javascript Frontend. The problem I encountered was about the format of the timestamp the API was sending its object with.

The timestamps were in microseconds timestamp whereas Php class DateTime only deals with second timestamps (through the string format 'U').

Therefor, JMSSerializer which I used on this project, was creating dates from another time.

Create the Handler

The official documentation gives a good example of how to create a custom Handler. This example is about DateTime De/serialization which was perfect for my problem. BUT I couldn't replace the DateTimeHandler provided by the JMSSerializerBundle by the one I made.

How Handlers are chosen

The class JMS\Serializer\Handler\HandlerRegistry is made to register handler in a associative array with the structure `$this→handlers[$direction][$typeName][$format]`. It means that you can have only one handler for a association Direction + Class + Format.

The class JMS\SerializerBundle\DependencyInjection\Compiler\CustomHandlersPass is made to read the configuration to sort the Handlers to store in the HandlerRegistry. In this class, you can find a function called sortAndFlattenHandlersList with sort the handlers according the priority defined to each Handler (in the service declaration).

  private function sortAndFlattenHandlersList(array $allHandlers)
  {
      $sorter = function ($a, $b) {
          return $b[3] == $a[3] ? 0 : ($b[3] > $a[3] ? 1 : -1);
      };
      self::stable_uasort($allHandlers, $sorter);
      $handlers = [];
      foreach ($allHandlers as $handler) {
          list ($direction, $type, $format, $priority, $service, $method) = $handler;
          $handlers[$direction][$type][$format] = [$service, $method];
      }
      return $handlers;
  }

Solution

In order to be the last Handler, my DateTimeHandler had to be after the official one in this list of sorted Handlers. Given the default Handlers don't have any specific priority, the default one is used: 0. That's why I had to make my Handler service priority equals to -1.

how_to_overwrite_the_default_handler_jmsserializer.txt · Dernière modification: 2019/12/17 11:58 par olivier