Symfony反序列化JSON时映射异名源键到自定义对象属性
Symfony Serializer 自定义字段映射实现方法
你当前调用的$this->serializer->deserialize()是Symfony Serializer组件的方法,不存在@Serializer\DeserializeName注解,直接用组件原生提供的@SerializedName(PHP8环境下为#[SerializedName]属性)即可实现JSON键和对象属性的映射,多余字段无需额外配置即可自动忽略。
方法1:实体类注解配置(推荐,双向生效)
直接在需要做名称映射的属性上添加对应注解,指定源JSON里的键名即可,不需要映射的addInfo5字段无需在类中定义属性,反序列化时会被自动丢弃。
PHP 8及以上版本用属性写法示例:
<?php namespace App\DTO; use Symfony\Component\Serializer\Annotation\SerializedName; class LabelMappings { // 键名和属性名完全一致的字段,不需要加任何注解 private string $type; private string $code; private ?string $arrow; private ?string $templateName; private string $rotationDegrees; // 自定义映射的字段,通过SerializedName指定源JSON键名 #[SerializedName('addInfo2')] private string $originCountry; #[SerializedName('addInfo3')] private string $gtin; #[SerializedName('addInfo4')] private ?string $wildfang; #[SerializedName('IdList')] private array $ids; // 补全对应属性的getter/setter方法即可 }
如果是PHP 7.x环境用注释注解,写法如下:
<?php namespace App\DTO; use Symfony\Component\Serializer\Annotation\SerializedName; class LabelMappings { // 其他同名字段省略... /** * @SerializedName("addInfo2") */ private $originCountry; /** * @SerializedName("addInfo3") */ private $gtin; // 其余映射字段按相同规则配置即可 }
注:该注解配置是双向生效的,后续将
LabelMappings实例序列化为JSON时,对应字段也会自动转换为你配置的键名。如果只需要反序列化时做名称映射、序列化保留原属性名,可以自定义实现NameConverterInterface的名称转换器传入Serializer即可。
方法2:反序列化上下文传映射配置(无需修改实体类)
如果你不想在实体类上加注解,也可以在调用deserialize方法时通过上下文参数传入字段映射关系:
$context = [ 'serialized_name_mapping' => [ LabelMappings::class => [ 'originCountry' => 'addInfo2', 'gtin' => 'addInfo3', 'wildfang' => 'addInfo4', 'ids' => 'IdList', ] ] ]; $labelMapping = $this->serializer->deserialize( $jsonLabelMappings, LabelMappings::class, 'json', $context );
两种方式都能直接实现你需要的映射效果,不需要额外写复杂的反序列化逻辑。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

