Symfony Serializer反序列化嵌套DTO数组失败问题求助
Symfony Serializer数组反序列化为DTO实例失败的问题排查与解决
我之前也碰到过一模一样的坑!单个嵌套DTO能正常转成实例,但数组里的元素愣是变成了普通关联数组,折腾了好一阵才找到问题根源,咱们一步步来搞定:
问题核心原因
你代码里的c属性能正常解析,是因为Serializer可以通过public NestedDto $c这个类型声明直接识别目标类型;但数组属性cs只靠@var NestedDto[]的注释,默认配置下Symfony Serializer没法自动识别数组内部的元素类型,再加上Normalizer的顺序不对,就导致数组元素被当成普通数组处理了。
具体修复步骤
1. 补充明确的类型注解
在TestDto的cs属性上,添加Symfony Serializer专属的@Type注解,明确指定数组元素的具体类型:
use Symfony\Component\Serializer\Annotation\Type; class TestDto { /** * @var NestedDto */ public NestedDto $c; /** * @var NestedDto[] * @Type("array<NestedDto>") */ public array $cs; }
这个注解会直接告诉Serializer:这个数组里的每一个元素,都要反序列化为NestedDto实例。
2. 调整Normalizer的执行顺序
在你的JsonSerializer构造函数里,把ArrayDenormalizer移到ObjectNormalizer前面。因为处理数组类型时,需要先让ArrayDenormalizer接管,它会根据@Type注解的信息,调用ObjectNormalizer去处理每个数组元素:
public function __construct() { $encoders = [new JsonEncoder()]; $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); $normalizers = [ new ArrayDenormalizer(), // 移到最前面优先处理数组 new ObjectNormalizer($classMetadataFactory, NULL, NULL, new ReflectionExtractor()), new DateTimeNormalizer(), ]; $this->serializer = new Serializer($normalizers, $encoders); $this->validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator(); }
验证修复结果
修改完成后再运行你的main函数,输出的TestDto对象里的cs数组就会变成:
TestDto Object ( [c] => NestedDto Object ( [s] => nested ) [cs] => Array ( [0] => NestedDto Object ( [s] => nested1 ) [1] => NestedDto Object ( [s] => nested2 ) ) )
完美解决问题!
内容的提问来源于stack exchange,提问作者Marian
相关产品推荐
相关产品推荐

