That serialization process of the :doc:`Serializer Component </serializer>` can be configured by the :ref:`serialization context <serializer-context>`, which can be built thanks to :ref:`context builders <serializer-using-context-builders>`.
Each built-in normalizer/encoder has its related context builder. However, you may want to create a custom context builder for your :doc:`custom normalizers </serializer/custom_normalizer>`.
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:
// 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:
$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:
// 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:
$legacyData = '{"updatedAt": "0000-00-00"}'; $context = (new LegacyContextBuilder()) ->withLegacyDates(true) ->toArray(); $serializer->deserialize($legacyData, MyModel::class, 'json', $context);