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

Symfony Serializer反序列化含对象数组的XML遇问题求助

解决Symfony Serializer反序列化XML数组到对象集合的问题

核心问题分析

你的XML结构中,<COMPONENT>节点下包含多个<item>子节点,Symfony Serializer默认无法自动识别这种嵌套结构需要映射为Component对象数组,尤其是单个<item>时会出现层级丢失的情况。需要通过注解配置或上下文参数明确XML节点与对象属性的映射规则,同时确保Serializer能正确读取类型信息。

解决方案步骤

1. 安装必要依赖

确保安装doctrine/annotations以支持注解解析:

composer require doctrine/annotations

2. 给实体类添加序列化注解

在实体类中使用Symfony的序列化注解,明确XML节点与属性的映射关系:

MyObject类

use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Serializer\Annotation\XmlList;

class MyObject
{
    /**
     * @SerializedName("RETURN")
     */
    private Return $return;

    /**
     * @var array<Component>
     * @SerializedName("COMPONENT")
     * @XmlList(entry="item") // 指定数组元素对应的XML子节点名称
     */
    private array $component = [];

    // 生成对应的getter/setter方法
    public function getReturn(): Return
    {
        return $this->return;
    }

    public function setReturn(Return $return): void
    {
        $this->return = $return;
    }

    public function getComponent(): array
    {
        return $this->component;
    }

    public function setComponent(array $component): void
    {
        $this->component = $component;
    }
}

Return类

use Symfony\Component\Serializer\Annotation\SerializedName;

class Return
{
    /**
     * @SerializedName("TYPE")
     */
    private string $type;

    public function getType(): string
    {
        return $this->type;
    }

    public function setType(string $type): void
    {
        $this->type = $type;
    }
}

Component类

use Symfony\Component\Serializer\Annotation\SerializedName;

class Component
{
    /**
     * @SerializedName("ID")
     */
    private int $id;

    public function getId(): int
    {
        return $this->id;
    }

    public function setId(int $id): void
    {
        $this->id = $id;
    }
}

3. 配置Serializer以支持注解和类型提取

修改Serializer实例的配置,添加注解加载器和复合类型提取器,确保能读取注解规则和属性类型:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Doctrine\Common\Annotations\AnnotationReader;

// 初始化注解读取器与类元数据工厂
$classMetadataFactory = new ClassMetadataFactory(
    new AnnotationLoader(new AnnotationReader())
);

// 组合PhpDoc和反射提取器,确保能识别数组元素类型
$propertyInfoExtractor = new PropertyInfoExtractor(
    typeExtractors: [new PhpDocExtractor(), new ReflectionExtractor()]
);

// 创建Serializer实例
$serializer = new Serializer(
    [
        new ArrayDenormalizer(),
        new ObjectNormalizer(
            classMetadataFactory: $classMetadataFactory,
            propertyTypeExtractor: $propertyInfoExtractor
        ),
    ],
    [new XmlEncoder()]
);

4. 执行反序列化

现在可以正常反序列化XML内容,无论是多个<item>还是单个<item>,都会正确映射为Component对象数组:

$xmlContent = <<<XML
<?xml version="1.0"?>
<ROOT>
  <RETURN>
    <TYPE>test</TYPE>
  </RETURN>
  <COMPONENT>
    <item>
      <ID>1</ID>
    </item>
    <item>
      <ID>2</ID>
    </item>
  </COMPONENT>
</ROOT>
XML;

/** @var MyObject $myObject */
$myObject = $serializer->deserialize($xmlContent, MyObject::class, 'xml');

// 验证结果
var_dump($myObject->getComponent()); // 输出包含2个Component对象的数组

替代方案:使用上下文参数(无需注解)

如果不想用注解,可以在反序列化时通过上下文参数指定映射规则:

$myObject = $serializer->deserialize(
    $xmlContent,
    MyObject::class,
    'xml',
    [
        XmlEncoder::ROOT_NODE_NAME => 'ROOT',
        ObjectNormalizer::ATTRIBUTES => [
            'return' => ['SerializedName' => 'RETURN'],
            'component' => [
                'SerializedName' => 'COMPONENT',
                'XmlList' => ['entry' => 'item'],
            ],
        ],
        ObjectNormalizer::PROPERTY_TYPE_EXTRACTOR => $propertyInfoExtractor,
    ]
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:53:14