Problem
I have the following object graph:
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
)
)
)
and the serialization using the following code from my controller:
$s = $this->get("serializer")->serialize($person, 'xml');
and this gives me the following result:
<response>
<name>Person Name</name>
<age>10</age>
<phones>
<phone>221-16-78</phone>
</phones>
<phones>
<phone>221-16-78</phone>
</phones>
</response>
The deserialization using the following code:
$this->get("serializer")->deserialize($s, 'AppBundle\Controller\Person', 'xml');
is giving the following 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] => Array
(
[phone] => 221-16-78
)
[1] => Array
(
[phone] => 221-16-78
)
)
)
Question
First, is there a way to receive an xml as follows:
<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>
And second, how can I deserialize it back to an object graph (Person and Telephone), once using simple deserialize it returns an object person with an array of phones that holds an associative array instead of Telephone objects.
Model / Controller
Here my model / controller classes:
<?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;
}
}
And my controller method:
/**
* @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);
}
Solution using JMS Serializer
I was able to solve this issue with JMS Serializer by providing some hints to serializer using annotations (basically type and list details) as follows:
<?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;
}
}