У меня есть следующий объект графа:
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>
И, во-вторых, как я могу десериализовать его обратно в граф объектов (Персона и Телефон), однажды используя простую десериализацию, он возвращает объект персона с массивом телефонов, который содержит ассоциативный массив вместо 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 Serializer, предоставив некоторые подсказки сериализатору с помощью аннотаций (в основном, типов и списков) следующим образом:
<?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;
Этого может быть достаточно, чтобы получить двухстороннюю сериализацию, которую вы ищете.
Других решений пока нет …