使用JMS\SerializedName获取嵌套JSON字段值失败的解决方案咨询
问题:JMS序列化器无法将JSON嵌套字段映射到模型属性
问题场景
现有JSON数据结构:
{ "CheckSum": { "NumberRecordings": "1", "Total": "1" } }
定义了RegisterModel模型:
final class RegisterModel { #[ Assert\NotBlank, JMS\SerializedName('CheckSum.NumberRecordings') ] private string $contractNumber; }
通过以下代码反序列化:
final readonly class XmlParseAction implements FileParseStrategyInterface { public function __construct( private JMS\Serializer\SerializerInterface $serializer ) {} public function __invoke(string $jsonDocument) { $model = $this->serializer->deserialize($jsonDocument, RegisterModel::class, 'json'); } }
发现$contractNumber字段值始终为null,但一级字段的反序列化工作正常。
解决方案
JMS序列化器的SerializedName注解中使用点号(.)的路径写法仅适用于XML格式,JSON格式不支持这种嵌套字段的直接映射。可以通过以下两种方案解决:
方案一:定义嵌套子模型(推荐)
创建对应嵌套结构的子模型,再通过Accessor将嵌套字段映射到目标属性:
- 定义
CheckSumModel子模型:
final class CheckSumModel { #[JMS\SerializedName('NumberRecordings')] private string $numberRecordings; public function getNumberRecordings(): string { return $this->numberRecordings; } public function setNumberRecordings(string $numberRecordings): void { $this->numberRecordings = $numberRecordings; } }
- 修改
RegisterModel,通过Accessor关联嵌套字段:
final class RegisterModel { #[JMS\SerializedName('CheckSum')] private CheckSumModel $checkSum; #[ Assert\NotBlank, JMS\Accessor(getter: 'getContractNumber') ] private string $contractNumber; public function getContractNumber(): string { return $this->checkSum->getNumberRecordings(); } public function setCheckSum(CheckSumModel $checkSum): void { $this->checkSum = $checkSum; } }
方案二:手动赋值嵌套字段
如果不想创建子模型,可以先将JSON反序列化为数组,再手动提取嵌套字段赋值给模型:
public function __invoke(string $jsonDocument) { $data = json_decode($jsonDocument, true); $model = new RegisterModel(); $model->setContractNumber($data['CheckSum']['NumberRecordings']); }
注:此方法需要给RegisterModel的$contractNumber字段添加对应的setter方法。
内容的提问来源于stack exchange,提问作者Angus123
相关产品推荐
相关产品推荐

