Implement a DateTimeInterface Handler for JMSSerializer

While working on an API today I realized the JMSSerializer does not support neither DateTimeInteface nor DateTimeImmutable. I am going to walk you through the necessary steps to serialize DateTimeImmutable objects using JMSSerializer.

Building an own handler requires not much code. The only problem is that documentation is scattered to many places and sometimes hard to find. I’m working on a full-stack Symfony 2.8 with JMSSerializerBundle installed. So make sure you are on the same page before starting.

The first step is to create a Handler:

<?php

namespace AppBundle\JmsSerializer;

use DateTimeInterface;
use JMS\Serializer\VisitorInterface;

class DateTimeInterfaceHandler
{
    public function serializeToJson(VisitorInterface $visitor, DateTimeInterface $dateTime, array $type)
    {
        return $dateTime->format(DATE_ATOM);
    }
}

You could also create a Subscriber, but I think the Handler is more straight forward. Read the JMSSerializer Documentation on Handlers to learn more.

Next we have to register our Handler as a service:

# services.yml
services:
  app.jmsserializer.datetimeinterface_handler:
    class: AppBundle\JmsSerializer\DateTimeInterfaceHandler
    tags:
      - { name: jms_serializer.handler, type: DateTimeImmutable, direction: serialization, format: json, method: serializeToJson }

This is documented in the JMSSerializerBundle Documentation, but setting my Service to private did not work (learn more about Private Services in Symfony), and setting the type to DateTimeInterface did not work either.

So if you use want to format DateTime as well you have to adjust the config value in the Bundle’s configuration:

# config.yml
jms_serializer:
  handlers:
    datetime:
      default_format: 'c' # ISO8601

That’s it. Now your DateTime and DateTimeImmutable objects should be serialized to string similar to 2016-09-28T12:54:07+00:00. If you encounter problems or have further questions find me on Twitter.