将复杂对象图序列化为XML并返回


Serialize Complex Object Graph to XML and Back

问题

我有以下对象图:

AppBundle'Controller'Person Object
(
    [name:AppBundle'Controller'Person:private] => Person Name
    [age:AppBundle'Controller'Person:private] => 10
    [phones:AppBundle'Controller'Person:private] => Array
        (
            [0] => AppBundle'Controller'Telephone Object
                (
                    [phone:AppBundle'Controller'Telephone:private] => 221-16-78
                )
            [1] => AppBundle'Controller'Telephone Object
                (
                    [phone:AppBundle'Controller'Telephone:private] => 221-16-78
                )
        )
)

以及使用来自我的控制器的以下代码进行序列化:

$s = $this->get("serializer")->serialize($person, 'xml');

这给了我以下结果:

<response>
  <name>Person Name</name>
  <age>10</age>
  <phones>
    <phone>221-16-78</phone>
  </phones>
  <phones>
    <phone>221-16-78</phone>
  </phones>
</response>

使用以下代码的反序列化:

$this->get("serializer")->deserialize($s, 'AppBundle'Controller'Person', 'xml');

正在返回以下内容:

AppBundle'Controller'Person Object
(
    [name:AppBundle'Controller'Person:private] => Person Name
    [age:AppBundle'Controller'Person:private] => 10
    [phones:AppBundle'Controller'Person:private] => Array
        (
            [0] => Array
                (
                    [phone] => 221-16-78
                )
            [1] => Array
                (
                    [phone] => 221-16-78
                )
        )
)

问题

首先,是否有如下接收xml的方法:

<response>
  <name>Person Name</name>
  <age>10</age>
  <phones>
    <telephone>
      <phone>221-16-78</phone>
    </telephone>
    <telephone>
      <phone>221-16-78</phone>
    </telephone>
  </phones>
</response>

第二,我如何将它反序列化回对象图(Person和Telephone),一旦使用简单的反序列化,它将返回一个对象Person和一个电话数组,该数组包含一个关联数组,而不是Telephone对象。

型号/控制器

这里是我的型号/控制器类:

<?php
namespace AppBundle'Controller;
class Person {
    private $name;
    private $age;
    private $phones;
    public function getName() {
        return $this->name;
    }
    public function getAge() {
        return $this->age;
    }
    public function getPhones() {
        return $this->phones;
    }
    public function setName($name) {
        $this->name = $name;
    }
    public function setAge($age) {
        $this->age = $age;
    }
    public function setPhones($phones) {
        $this->phones = $phones;
    }
}
<?php
namespace AppBundle'Controller;
class Telephone {
    private $phone;
    public function getPhone() {
        return $this->phone;
    }
    public function setPhone($phone) {
        $this->phone = $phone;
    }
}

我的控制器方法:

/**
 * @Route("/", name="homepage")
 */
public function indexAction(Request $request)
{
    $phone1 = new Telephone();
    $phone1->setPhone("221-16-78");
    $phone2 = new Telephone();
    $phone2->setPhone("221-16-78");
    $person = new Person();
    $person->setName("Person Name");
    $person->setAge(10);
    $person->setPhones(array($phone1, $phone2));
    print_r($person);
    $s = $this->get("serializer")->serialize($person, 'xml');
    $p = $this->get("serializer")->deserialize($s, 'AppBundle'Controller'Person', 'xml');
    print_r($p);
}

使用JMS序列化程序的解决方案

通过使用注释(基本上是类型和列表详细信息)向序列化程序提供一些提示,我能够使用JMS序列化程序解决这个问题,如下所示:

<?php
namespace AppBundle'Controller;
use JMS'Serializer'Annotation'Type;
use JMS'Serializer'Annotation'XmlList;
class Person {
    /**
     * @Type("string")
     */
    private $name;
    /**
     * @Type("integer")
     */
    private $age;
    /**
     * @Type("array<AppBundle'Controller'Telephone>")
     * @XmlList(entry = "telephone")
     */
    private $phones;
    public function getName() {
        return $this->name;
    }
    public function getAge() {
        return $this->age;
    }
    public function getPhones() {
        return $this->phones;
    }
    public function setName($name) {
        $this->name = $name;
    }
    public function setAge($age) {
        $this->age = $age;
    }
    public function setPhones($phones) {
        $this->phones = $phones;
    }
}
<?php
namespace AppBundle'Controller;
use JMS'Serializer'Annotation'Type;
class Telephone {
    /**
     * @Type("string")
     */
    private $phone;
    public function getPhone() {
        return $this->phone;
    }
    public function setPhone($phone) {
        $this->phone = $phone;
    }
}

据我所知,当您执行$this->get('serializer')时,您得到的是Symfony Serialization组件。我并不完全熟悉它(你会在勾选中看到原因),但他们的文档确实强调了如何处理对象属性,尽管只是为了序列化。

对于您似乎正在寻找的对序列化视图的控制类型,我强烈建议使用JMS序列化程序(和相关的捆绑包),它可以通过注释或外部配置对输出进行更细粒度的控制。在你的情况下,做:

use JMS'Serializer'Annotation as Serializer;
class Person
{
    /**
     * @Serializer'Type("array<Telephone>")
     */
    private $phones;

可能足以获得您正在寻找的双向序列化。