Symfony 6 deserializer反序列化时所有字段返回null如何解决
问题根因
- 配置传参错误:
disable_type_enforcement要求传入布尔值,代码中传的是字符串'true',Serializer组件做参数校验时用严格类型判断,字符串值不会被识别为有效开启配置,类型校验不通过时组件会直接放弃属性赋值。 - XML解析层级错位:XmlEncoder默认从XML根节点开始做结构映射,你使用的XML根节点是
<Items>,实际Item数据存储在它的子节点<Item>下,直接反序列化到Item类时,组件拿到的顶层数组只有Item这一个键,找不到和Item类属性匹配的键,所有字段自然会被赋值为null。 - 处理器缺失:只注册了
ObjectNormalizer,没有注册ArrayDenormalizer,遇到嵌套数组结构时无法递归做数据映射。 - 属性访问限制:如果Item类的属性是private修饰,且没有编写对应public的setter方法,ObjectNormalizer默认没有权限修改私有属性值,也会导致赋值失败。
修复步骤
- 修正参数类型,把
'disable_type_enforcement'=> 'true'改成'disable_type_enforcement' => true,严格传入布尔值。 - 补全Normalizer并调整加载顺序:把
ArrayDenormalizer放在ObjectNormalizer之前注册,保证嵌套结构能被正确解析。 - 对齐XML解析层级:
不需要修改XML结构的话,先把XML解码成数组,取出内层Item键对应的数据,再做反序列化映射即可;如果可以调整XML结构,直接把根节点改成<Item>,同时在上下文里配置xml_root_node_name => 'Item'就能直接完成反序列化。 - 检查实体访问权限:要么给所有私有属性加上命名匹配的public setter方法(比如
id属性对应setId()方法),要么初始化ObjectNormalizer时传入PropertyAccessor实例,开启反射直接读写私有属性的能力。
参考修复代码:
$data = file_get_contents('file.xml'); $encoders = [new XmlEncoder(), new JsonEncoder()]; // 注意顺序:ArrayDenormalizer必须放在ObjectNormalizer前面 $normalizers = [new ArrayDenormalizer(), new ObjectNormalizer()]; $serializer = new Serializer($normalizers, $encoders); // 适配<Items>根节点嵌套<Item>子节点的XML结构 $xmlArray = $serializer->decode($data, 'xml'); $item = $serializer->denormalize($xmlArray['Item'], Item::class, null, [ 'disable_type_enforcement' => true ]);
如果XML标签存在行内属性(比如
<Item sku="123">这种写在标签尖括号内的属性,不是独立子节点存值),可以额外配置XmlEncoder::AS_COLLECTION => false,同时过滤掉空白文本节点,避免解析出@、#开头的特殊键导致映射失败。
内容的提问来源于stack exchange,提问作者jazz
相关产品推荐
相关产品推荐

