You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony5.4自定义序列化器如何处理属性Context注解?

问题

基于Symfony 5.4开发应用,定义了如下Client类:

class Client
{
    #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
    public \DateTimeImmutable $passportIssuedDate;

    #[Context([DateTimeNormalizer::FORMAT_KEY => \DateTimeImmutable::ATOM])]
    public \DateTimeImmutable $agreementDateTime;
}

自定义序列化器代码如下:

$encoders = [new JsonEncoder()];
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizers = [
    new DateTimeNormalizer(),
    new ObjectNormalizer(propertyTypeExtractor: $extractor),
];
$serializer = new Serializer($normalizers, $encoders);

调用自动注入的标准序列化器:

$this->serializer->serialize($client, 'json');

得到正确结果:

{"passportIssuedDate":"2024-04-05","agreementDateTime":"2024-04-05T11:59:32+00:00"}

但使用自定义序列化器时,结果为:

{"passportIssuedDate":"2024-04-05T11:59:32+00:00","agreementDateTime":"2024-04-05T11:59:32+00:00"}

需修改自定义序列化器,使其正确处理属性的Context注解。

解决方案

自定义序列化器未识别Context注解,是因为ObjectNormalizer缺少读取注解元数据的能力。需添加注解读取相关组件,让序列化器能解析并应用属性上的Context配置。

修改后的自定义序列化器代码如下:

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\AttributeMetadataFactory\ContextAwareAttributeMetadataFactory;

// 1. 构建注解读取器与类元数据工厂,用于读取属性上的Context注解
$classMetadataFactory = new ClassMetadataFactory(
    new AnnotationLoader(new AnnotationReader())
);

// 2. 包装元数据工厂,使其能解析Context注解并转化为序列化上下文配置
$contextAwareMetadataFactory = new ContextAwareAttributeMetadataFactory(
    $classMetadataFactory
);

$encoders = [new JsonEncoder()];
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizers = [
    new DateTimeNormalizer(),
    // 3. 给ObjectNormalizer传入支持Context注解的元数据工厂
    new ObjectNormalizer(
        classMetadataFactory: $contextAwareMetadataFactory,
        propertyTypeExtractor: $extractor
    ),
];
$serializer = new Serializer($normalizers, $encoders);

核心逻辑说明:

  • ClassMetadataFactory + AnnotationLoader + AnnotationReader组合,负责扫描类和属性上的序列化注解;
  • ContextAwareAttributeMetadataFactory会将属性上的Context注解内容,转化为序列化时的上下文参数;
  • 给ObjectNormalizer传入上述元数据工厂后,序列化过程中就能根据每个属性的Context注解,应用对应的日期格式化规则。

内容的提问来源于stack exchange,提问作者Andrew Markhai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:05:10