跳到内容

如何创建自定义上下文构建器

编辑此页

Serializer 组件的序列化过程可以通过序列化上下文进行配置,而序列化上下文可以通过上下文构建器来构建。

每个内置的规范化器/编码器都有其相关的上下文构建器。但是,您可能希望为您的自定义规范化器创建自定义上下文构建器。

创建一个新的上下文构建器

假设您想以不同的方式处理日期反规范化,如果日期来自遗留系统,则当序列化值为 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 = []): 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);
    }
}

现在您可以在反规范化期间将零值日期转换为 null

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

现在,为了避免记住这个特定的 zero_date_to_null 上下文键,您可以创建一个专用的上下文构建器

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);
    }
}

最后,使用它来构建序列化上下文

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);
这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本