Reputation: 8496
I have the following XML:
<CinemaListExport>
<Cinema>
....
<screens>
<screen></screen>
<screen></screen>
</screens>
</Cinema>
<Cinema>
....
</Cinema>
<CinemaListExport>
I am trying to convert this into the following objects:
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 = [];
with the following code:
$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');
No matter what I do I always get the following:
class CinemaList#265 (1) {
public $cinema =>
class Doctrine\Common\Collections\ArrayCollection#317 (1) {
private $elements =>
array(0) {
}
}
}
Can anyone point me in the right direction? What am I doing wrong here? I just need CinemaList to contain all the Cinemas and each Cinema to contain all it's screens
Upvotes: 0
Views: 1857
Reputation: 639
Well i had to develop your solution and made some search to understand why this simply use case doesn't work.
First you miss the normalizer ArrayDenormalizer
it's required to unserialize your collections of cinema and screen:
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()]
);
Without this normalizer array and collection are just skipped.
There is another thing about serializing/unserializing and in particular with the ObjectNormalizer
which use PropertyAccess
component.
You have to implement both method adder
and remover
if you want to make it works.
A lot of things happens in the PropertyAccessor::writeProperty methods. I won’t explain all the mecanism, but shortly: if you have methods addXXX and removeXXX, then addXXX will be used in priority. Take care ! if you only have the addXXX method, then it won’t be used… I don’t know why they did this but there is certainly a good reason. The second options is the setter. If it exists (and you don’t have removeXXX or addXXX), then it will be used to add the items from the collections.
from here
I did some successfull test in a new symfony project. If you still run into issues i'll be glad to help you.
Upvotes: 2