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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:02:27