Skip to content

How to Create your Custom Context Builder

Edit this page

That serialization process of the Serializer Component can be configured by the serialization context, which can be built thanks to context builders.

Each built-in normalizer/encoder has its related context builder. However, you may want to create a custom context builder for your custom normalizers.

Creating a new Context Builder

Let's imagine that you want to handle date denormalization differently if they are coming from a legacy system, by converting dates to null if the serialized value is 0000-00-00. To do that you'll first have to create your normalizer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// src/Serializer/ZeroDateTimeDenormalizer.php
namespace App\Serializer;

use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

final class ZeroDateTimeDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
    use DenormalizerAwareTrait;

    public function denormalize($data, string $type, ?string $format = null, array $context = []): mixed
    {
        if ('0000-00-00' === $data) {
            return null;
        }

        unset($context['zero_datetime_to_null']);

        return $this->denormalizer->denormalize($data, $type, $format, $context);
    }

    public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
    {
        return true === ($context['zero_datetime_to_null'] ?? false)
            && is_a($type, \DateTimeInterface::class, true);
    }
}

Now you can cast zero-ish dates to null during denormalization:

1
2
$legacyData = '{"updatedAt": "0000-00-00"}';
$serializer->deserialize($legacyData, MyModel::class, 'json', ['zero_datetime_to_null' => true]);

Now, to avoid having to remember about this specific zero_date_to_null context key, you can create a dedicated context builder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Serializer/LegacyContextBuilder
namespace App\Serializer;

use Symfony\Component\Serializer\Context\ContextBuilderInterface;
use Symfony\Component\Serializer\Context\ContextBuilderTrait;

final class LegacyContextBuilder implements ContextBuilderInterface
{
    use ContextBuilderTrait;

    public function withLegacyDates(bool $legacy): static
    {
        return $this->with('zero_datetime_to_null', $legacy);
    }
}

And finally, use it to build the serialization context:

1
2
3
4
5
6
7
$legacyData = '{"updatedAt": "0000-00-00"}';

$context = (new LegacyContextBuilder())
    ->withLegacyDates(true)
    ->toArray();

$serializer->deserialize($legacyData, MyModel::class, 'json', $context);
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version