Symfony序列化程序将带有子级的XML反序列化为对象

时间:2019-05-08 13:01:58

标签: php serialization symfony4

我有以下XML:

<CinemaListExport>
    <Cinema>
        ....
        <screens>
            <screen></screen>
            <screen></screen>
        </screens>
    </Cinema>
    <Cinema>
    ....
    </Cinema>
<CinemaListExport>

我正在尝试将其转换为以下对象:

class CinemaList
{
    /**
     * @var Cinema[]
     */
    public $cinema;

    public function __construct()
    {
        $this->cinema = new ArrayCollection();
    }

    public function addCinema(Cinema $cinema)
    {
        $this->cinema[] = $cinema;
    }
class Cinema
{
    fields...

    /**
     * @var Screen[]
     */
    public $screens = [];

具有以下代码:

        $normalizers = [
            new ArrayDenormalizer(),
            new ObjectNormalizer(null, null, null, new ReflectionExtractor())
        ];
        $encoders = [new XmlEncoder()];

        $serializer = new Serializer($normalizers, $encoders);


        $res = $serializer->deserialize($xml, CinemaList::class, 'xml');

无论我做什么,我总是得到以下信息:

class CinemaList#265 (1) {
  public $cinema =>
  class Doctrine\Common\Collections\ArrayCollection#317 (1) {
    private $elements =>
    array(0) {
    }
  }
}

有人能指出我正确的方向吗?我在这里做错了什么? 我只需要CinemaList包含所有影院,每个影院都包含所有屏幕

1 个答案:

答案 0 :(得分:1)

好吧,我不得不开发您的解决方案并进行一些搜索,以了解为什么这种简单的用例无法正常工作。

首先,您错过了归一化器ArrayDenormalizer,需要对电影和屏幕集合进行反序列化:

use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$objectNormalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());

$serializer = new Serializer(
    [new ArrayDenormalizer(), $objectNormalizer], [new XmlEncoder()]
);

没有这个规范化器数组和集合就被跳过。

关于序列化/反序列化还有另一件事,尤其是使用ObjectNormalizer组件的PropertyAccess

如果要使其工作,则必须同时实现方法adderremover

  

PropertyAccessor :: writeProperty方法中发生了很多事情。我不会解释所有的机制,但是很快:如果您有方法addXXX和removeXXX,则将优先使用addXXX。照顾自己 !如果您仅具有addXXX方法,则将不会使用该方法……我不知道他们为什么这样做,但是当然有充分的理由。   第二个选项是二传手。如果存在(并且您没有removeXXX或addXXX),那么它将用于添加集合中的项目。

来自here

我在一个新的symfony项目中进行了一些成功的测试。如果您仍然遇到问题,我们将很乐意为您提供帮助。