How to Create your Custom Context Builder
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);