Symfony 6 串行器

问题描述 投票:0回答:1

嗨,我需要使用 symfony 6 对该数据进行非规范化

array:4 [
  "createdAt" => array:3 [
    "date" => "2024-01-09 17:04:37.209330"
    "timezone_type" => 3
    "timezone" => "Europe/Paris"
  ]
  "utilisateur" => "phpunit"
  "type" => "CREATION"
  "texte" => "creation de la demande"
]

对于这个物体

class Historique
{
    public \DateTime $createdAt;

    public function __construct(public readonly string $utilisateur, public readonly string $type, public readonly ?string $texte)
    {
        $this->createdAt = new \DateTime();
    }

    public function getTypeLabel(): string
    {
        return HistoriqueTypeEnum::getLabelName($this->type);
    }
}

我已经使用了这段代码,但我在对日期时间进行非规范化时遇到问题

$normalizers = [
    new DateTimeNormalizer(),
    new ObjectNormalizer(null, null, null, new ReflectionExtractor()),
    new BackedEnumNormalizer(),
];
$serializer = new Serializer($normalizers, [new JsonEncoder()]);
$serializer->denormalize($historique, Historique::class, 'json', [DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s',]);

我遇到此错误(“数据不是字符串、空字符串或 null;您应该传递一个可以使用传递的格式或有效的日期时间字符串进行解析的字符串。”)。

如果我像这样改变标准化器的顺序

$normalizers = [
    new ObjectNormalizer(null, null, null, new ReflectionExtractor()),
    new BackedEnumNormalizer(),
    new DateTimeNormalizer(),
];

我遇到此错误(无法从序列化数据创建“DateTimeZone”实例,因为其构造函数需要存在以下参数:“$timezone”。)

感谢您的帮助

symfony serialization
1个回答
0
投票

在非规范化过程中,

createdAt
需要一个字符串。必须设置
#[Ignore]
属性,以便不处理该属性。为了处理属性
#[Ignore]
,必须设置
ClassMetadataFactory

历史

use Symfony\Component\Serializer\Annotation\Ignore;

class Historique
{
    #[Ignore]
    public \DateTime $createdAt;

    public function __construct()
    {
        $this->createdAt = new \DateTime();
    }
}

示例+测试

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

class HistoriqueTest extends KernelTestCase
{
    public function testHistorique()
    {
        $historique = new Historique();

        $normalizers = [
            new DateTimeNormalizer(),
            new ObjectNormalizer(
                new ClassMetadataFactory(new AnnotationLoader(null)),
                null,
                null,
                new ReflectionExtractor()
            ),
            new BackedEnumNormalizer()
        ];

        $serializer = new Serializer($normalizers, [new JsonEncoder()]);
        $result = $serializer->denormalize(
           $historique,
           Historique::class,
           'json',
           [DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s']
        );

        $this->assertInstanceOf(\DateTime::class, $result->createdAt);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.