You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony Serializer:如何将带属性的XML反序列化为对象数组?

PHP Symfony Serializer - 将XML反序列化为对象数组

问题描述

如何将带有属性的XML反序列化为对象数组?

现有代码

XML字符串:

$string = '<?xml version="1.0" encoding="UTF-8" ?>
<response>
    <item flight="23"/>
    <item flight="24"/>
</response>';

Serializer初始化逻辑:

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$metadataAwareNameConverter = new MetadataAwareNameConverter($classMetadataFactory);

$serializer = new Serializer(
    [new ArrayDenormalizer(), new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter)],
    [new XmlEncoder()]
);
$objects = $serializer->deserialize($string, 'App\Entities\Item[]', 'xml');

Item实体类:

class Item
{
    #[SerializedName('@flight')]
    public string $flight;
}

当前错误结果

array:1 [
  "item" => App\Entities\Item
]

问题原因

Symfony的XmlEncoder默认会将多个同名子节点包装在以节点名为键的关联数组中(即['item' => [Item实例1, Item实例2]]),但直接指定目标类型为Item[]时,序列化器无法自动识别该嵌套结构,只会提取item键下的单个对象(或仅处理第一个节点)。

解决方案

方案1:使用DTO包装数组

创建对应XML根节点的DTO类,用来承载Item对象数组:

class ResponseDTO
{
    #[SerializedName('item')]
    /** @var Item[] */
    public array $items;
}

修改反序列化逻辑,先解析为DTO再提取目标数组:

$responseDto = $serializer->deserialize($string, ResponseDTO::class, 'xml');
$objects = $responseDto->items;

方案2:配置XmlEncoder的集合选项

在反序列化时通过上下文参数,明确告知编码器将item节点作为集合处理:

use Symfony\Component\Serializer\Encoder\XmlEncoder;

$objects = $serializer->deserialize(
    $string,
    'App\Entities\Item[]',
    'xml',
    [XmlEncoder::AS_COLLECTION => ['item' => true]]
);

也可以在创建XmlEncoder时直接设置默认集合规则:

use Symfony\Component\Serializer\Encoder\XmlEncoder;

$encoder = new XmlEncoder(null, null, [XmlEncoder::AS_COLLECTION => ['item' => true]]);
$serializer = new Serializer(
    [new ArrayDenormalizer(), new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter)],
    [$encoder]
);
$objects = $serializer->deserialize($string, 'App\Entities\Item[]', 'xml');

验证结果

修改后,$objects会变成包含两个Item实例的索引数组:

array:2 [
  0 => App\Entities\Item {#xxx
    +flight: "23"
  }
  1 => App\Entities\Item {#xxx
    +flight: "24"
  }
]

内容的提问来源于stack exchange,提问作者Kanat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:23:20