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
相关产品推荐
相关产品推荐

