Symfony嵌套对象反序列化报错:日期字段类型不匹配
问题描述
使用Symfony Serializer组件反序列化JSON数据到PropertyPromotionDto和NestedDto时,出现类型转换错误:
类"App\Dto\NestedDto"的"date"属性类型必须为"App\Dto\DateTimeImmutable"(传入的是"string"类型)
相关代码如下:
DTO类代码
#[Assert\Cascade] class PropertyPromotionDto { public function __construct( private string $name, #[Assert\NotBlank(message: 'Не может быть пустым')] private int $value, #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i'])] private DateTimeImmutable $date, private NestedDto $nestedDto, /** @var NestedDto[] */ private array $nestedDtos, private Phone $phone ) { } } class NestedDto { public function __construct( #[Assert\NotBlank(message:"Не должен быть пустым")] private string $author, private int $age, private ?DateTimeImmutable $date = null, private ?Phone $phone, // 此处存在多余逗号,建议移除 ){ } }
JSON数据
{ "name":"Mane", "value":42, "nestedDto": {"author": "Jane", "age": 35, "date":"2023-09-12"}, "nestedDtos": [ {"author": "", "age": 20, "date":"2023-09-12"}, {"author": "Pane", "age": 22} ] }
Serializer配置代码
$encoder = [new JsonEncoder()]; $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]); $normalizer = [new ArrayDenormalizer(), new ObjectNormalizer(null, null, null, $extractor)]; $serializer = new \Symfony\Component\Serializer\Serializer($normalizer, $encoder); return $serializer->deserialize($data, $type, $format);
解决方案
1. 添加DateTimeNormalizer到Serializer配置
当前配置缺少处理日期字符串转DateTimeImmutable的DateTimeNormalizer,需将其加入normalizer数组:
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; // ... $normalizer = [ new DateTimeNormalizer(), // 新增日期转换器 new ArrayDenormalizer(), new ObjectNormalizer(null, null, null, $extractor) ];
2. 为NestedDto的date字段指定格式
JSON中传入的date是Y-m-d格式,需给NestedDto的date属性添加格式注解:
use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; // ... class NestedDto { public function __construct( #[Assert\NotBlank(message:"Не должен быть пустым")] private string $author, private int $age, #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])] // 指定日期格式 private ?DateTimeImmutable $date = null, private ?Phone $phone // 移除多余逗号 ){ } }
3. 修正DateTimeImmutable的命名空间
确保DTO类顶部引入全局的DateTimeImmutable,避免被解析为App\Dto\DateTimeImmutable:
// 在两个DTO类顶部添加 use DateTimeImmutable; use Symfony\Component\Validator\Constraints as Assert; // 其他必要的use语句...
4. (可选)全局配置日期格式
如果希望所有日期字段使用统一格式,可在实例化DateTimeNormalizer时传入默认配置,无需逐个字段加注解:
new DateTimeNormalizer([ DateTimeNormalizer::FORMAT_KEY => 'Y-m-d', DateTimeNormalizer::TIMEZONE_KEY => 'UTC' // 可选指定时区 ])
内容的提问来源于stack exchange,提问作者sveta600
相关产品推荐
相关产品推荐

