如何使用JMS Serializer反序列化含未知嵌套属性的JSON?
解决JMS序列化器中动态键嵌套JSON的反序列化问题
嗨,我来帮你搞定这个反序列化的问题!你遇到的场景是Layer对应的JSON里全是未知的动态键(比如480x960、720x360这种),想要把这些内容提取到Doctrine Collection里,还不用保留原来的键值结构对吧?下面给你两种具体的实现方案,看你是要提取键名还是对应的值:
修改Layer DTO实现需求
我们可以用JMS序列化器的注解先接收动态的键值对,再在反序列化完成后做数据处理,把需要的内容转成Collection。
场景1:把动态键名转成Collection
如果你希望通过$project->getLayer()->getItems()拿到包含480x960、720x360这些分辨率字符串的Collection,就用这个版本:
namespace App\DTO; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use JMS\Serializer\Annotation as Serializer; class Layer { /** * 临时存动态键值对的数组 * @var array * * @Serializer\Type("array<array>") // 这里的array<array>对应每个键的值是数组,要是值的类型不一样可以调整 */ private $dynamicData; /** * 最终存键名的Collection * @var Collection */ private $items; /** * 反序列化完自动处理数据 * @Serializer\PostDeserialize */ public function postDeserialize(): void { // 把所有键名提取出来转成Collection $this->items = new ArrayCollection(array_keys($this->dynamicData)); } public function getItems(): Collection { return $this->items; } }
场景2:把动态键对应的值转成Collection
要是你需要的是每个键对应的数组值(比如JSON里的[]),只需要改一下postDeserialize方法就行:
/** * @Serializer\PostDeserialize */ public function postDeserialize(): void { // 提取所有值到Collection,直接忽略键名 $this->items = new ArrayCollection(array_values($this->dynamicData)); }
额外优化:让getLayer()直接返回Collection
如果你不想多一层getItems(),希望调用$project->getLayer()就直接拿到Collection,可以调整你的Project DTO,直接把$layer定义为数组,在getter里转成Collection:
namespace App\DTO; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use JMS\Serializer\Annotation as Serializer; class Project { /** * @var array * * @Serializer\Type("array<array>") */ protected $layer; public function getLayer(): Collection { // 要键名就用array_keys,要值就用array_values return new ArrayCollection(array_keys($this->layer)); } }
这样反序列化之后,直接调用$project->getLayer()就能得到你想要的Collection啦~
内容的提问来源于stack exchange,提问作者Marcin Harasim
相关产品推荐
相关产品推荐

