Skip to content

How to Create your Custom Context Builder

Edit this page

The Serializer Component uses Normalizers and Encoders to transform any data to any data-structure (e.g. JSON). That serialization process can be configured thanks to a 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