Symfony序列化器反序列化集合对象时始终得到空集合,是否为组件Bug?
Symfony序列化器反序列化集合对象时始终得到空集合,是否为组件Bug?
这其实不是Symfony Serializer组件的Bug,是你的代码写法没适配序列化器的处理逻辑,我来帮你拆解问题和解决方案:
问题根源
你的Items类是readonly类,Symfony序列化器处理readonly类时,会优先通过构造函数实例化对象,而不是直接赋值公共属性。但这里有两个关键问题:
Items的构造函数用了可变参数Item ...$items,但JSON传入的items是一个数组,序列化器没办法自动将这个数组映射到可变参数上;- 序列化器需要明确知道JSON字段和构造函数参数的对应关系,可变参数的场景下这个映射关系需要额外提示。
而你直接把items数组放到Order类里能正常工作,是因为Order的构造函数参数明确是array $items,再加上PhpDoc的@var array<Item>标注,让PhpDocExtractor能正确识别数组元素类型,序列化器就能顺利完成反序列化。
解决方案
只需要给Items类的构造函数参数添加序列化提示,或者完善PhpDoc标注,让序列化器明确参数和JSON字段的对应关系即可:
方法1:使用SerializedName注解
use Symfony\Component\Serializer\Annotation\SerializedName; final readonly class Items { /** * @var array<Item> */ public array $items; /** * @param Item ...$items */ public function __construct(#[SerializedName('items')] Item ...$items) { $this->items = $items; } }
方法2:完善PhpDoc标注
如果不想用注解,也可以给构造函数参数添加更明确的PhpDoc,让PhpDocExtractor能识别参数和字段的对应:
final readonly class Items { /** * @var array<Item> */ public array $items; /** * @param array<Item> $items */ public function __construct(Item ...$items) { $this->items = $items; } }
这里把构造函数的@param标注为array<Item>,序列化器会自动把JSON数组映射到这个可变参数上。
验证效果
修改后再执行你的反序列化代码,$order->items->items就会正确包含两个Item对象了。
备注:内容来源于stack exchange,提问作者jazzzpor
相关产品推荐
相关产品推荐

