How to Create your Custom Context Builder

6.1

6.1

Context builders were introduced in Symfony 6.1.

コンテキストビルダーは Symfony 6.1 で導入されました。

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.

シリアライザー コンポーネントは、ノーマライザーとエンコーダーを使用して、任意のデータを任意のデータ構造 (JSON など) に変換します。そのシリアライゼーション プロセスは、コンテキスト ビルダーのおかげで構築できるシリアライゼーション コンテキストのおかげで構成できます。

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:

シリアル化された値が 0000-00-00 の場合に日付を null に変換することで、日付の非正規化をレガシー システムからのものである場合に別の方法で処理したいとします。そのためには、まずノーマライザーを作成する必要があります。
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 = [])
    {
        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 = [])
    {
        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:

非正規化中にゼロっぽい日付を null にキャストできるようになりました。
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:

ここで、この特定の zero_date_to_nullcontext キーについて覚える必要がないように、専用のコンテキスト ビルダーを作成できます。
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);