Symfony Serializer分组在Slim4+PHP8.3中不生效,求解决方案
问题描述
我正在使用PHP8.3和Slim4框架开发应用,引入Symfony Serializer进行对象的序列化与反序列化操作。
依赖配置(dependencies.php)
$containerBuilder->addDefinitions([ Serializer::class => function () { $encoders = [new JsonEncoder()]; $extractors = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]); $normalizers = [new ArrayDenormalizer(), new ObjectNormalizer(null, null, null, $extractors)]; return new Serializer($normalizers, $encoders); } ]);
实体类代码
<?php namespace App\Domain\Entity; use App\Application\Repository\CompanyRepository; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use Symfony\Component\Serializer\Annotation\Groups; #[Entity(repositoryClass: CompanyRepository::class), Table(name: 'companies')] class Company { #[Groups(['save-company'])] #[Column(type: 'string', length: 9, nullable: true)] private string $siren; #[Groups(['save-company'])] #[Column(type: 'string', length: 15, nullable: true)] private string $siret; #[Column(name: 'trading_name', type: 'string', length: 50, nullable: true)] private ?string $tradingName; public function getSiren(): string { return $this->siren; } public function setSiren(string $siren): void { $this->siren = $siren; } public function getSiret(): string { return $this->siret; } public function setSiret(string $siret): void { $this->siret = $siret; } public function getTradingName(): ?string { return $this->tradingName; } public function setTradingName(?string $tradingName): void { $this->tradingName = $tradingName; } }
反序列化代码
$this->sfSerializer->deserialize(json_encode($this->getFormData()), Company::class, JsonEncoder::FORMAT, [ AbstractNormalizer::OBJECT_TO_POPULATE => $company, AbstractNormalizer::GROUPS => ['save-company'] ]);
请求体
{ "siren": "SRN-1", "siret": "SRT-1", "tradingName": "my comany name" }
需求是仅反序列化siren和siret字段,但当前会处理所有属性,请问遗漏了什么配置?
解决方案
核心问题是:使用OBJECT_TO_POPULATE填充现有对象时,Symfony Serializer默认会处理所有存在setter方法的属性,不受Groups配置限制。要实现仅处理指定组内字段,需添加以下配置:
修改反序列化参数
添加AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES并设置为false,阻止Serializer处理未加入指定组的属性:
$this->sfSerializer->deserialize(json_encode($this->getFormData()), Company::class, JsonEncoder::FORMAT, [ AbstractNormalizer::OBJECT_TO_POPULATE => $company, AbstractNormalizer::GROUPS => ['save-company'], // 新增:禁止处理组外属性 AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false, ]);
补充说明
- 当
ALLOW_EXTRA_ATTRIBUTES设为false时,请求体中不在save-company组内的字段(如tradingName)会被直接忽略,不会调用对应的setTradingName方法。 - 如果需要对组外字段抛出异常,可额外添加配置:
AbstractNormalizer::EXTRA_ATTRIBUTES_EXCEPTION_CLASS => \Symfony\Component\Serializer\Exception\ExtraAttributesException::class,这样当请求包含组外字段时会直接报错。
内容的提问来源于stack exchange,提问作者walidtlili
相关产品推荐
相关产品推荐

