I have XML in the format
<POS>
<Source PseudoCCode="BOA" ISOCountry="US" AgentDutyCode="J114N">
<RequestorID Type="11" ID="T921">
<CompanyName Code="CP" CodeContext="123T"/>
</RequestorID>
</Source>
<Source>
<RequestorID Type="1" ID="34778"/>
</Source>
<Source>
<RequestorID Type="9" ID="ZF"/>
</Source>
<Source>
<RequestorID Type="17" ID="mabaan"/>
</Source>
</POS>
`
I have a php object that I want to deserialize into.
class POS
{
/**
* @ORM\OneToMany(targetEntity="POS_Source", mappedBy="POS", orphanRemoval=true)
* @Groups("Include")
*/
private $Source;
public function __construct()
{
$this->Source = new ArrayCollection();
}
/**
* @return ArrayCollection|OTA_POS_Source[]
*/
public function getSource(): ArrayCollection
{
return $this->Source;
}
public function addSource(POS_Source $source): self
{
if (!$this->Source->contains($source)) {
$this->Source[] = $source;
$source->setPOS($this);
}
return $this;
}
public function removeSource(POS_Source $source): self
{
if ($this->Source->contains($source)) {
$this->Source->removeElement($source);
// set the owning side to null (unless already changed)
if ($source->getPOS() === $this) {
$source->setPOS(null);
}
}
return $this;
}
When I do
$classMetadataFactory = new ClassMetadataFactory(
new AnnotationLoader(new AnnotationReader())
);
$metadataAwareNameConverter = new MetadataAwareNameConverter($classMetadataFactory);
$normalizers = [new DateTimeNormalizer(), new ArrayDenormalizer(),
new PropertyNormalizer(), new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter)];
$encoders = [new XmlEncoder(), new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$encoder = new XmlEncoder();
$output[] = $encoder->decode($data,'xml');
dump($output);
/**
* @var OTA_POS $pos
*/
$pos = $serializer->deserialize($data,POS::class,'xml');
$posSourceArray = $serializer->deserialize($pos->getSource(),'App\POS_Source[]','xml');
dump($posSourceArray);
It gives me the POS object but rather than a collection of POS_Source objects it gives be an array below.
POS {#839 ▼
-id: null
-Source: array:5 [▼
0 => array:4 [▶]
1 => array:1 [▶]
2 => array:1 [▶]
3 => array:1 [▶]
4 => array:1 [▶]
]
}
How can I make this work to populate the object tree all the way to the bottom. When I serialize from object structure to XML it works great.
Here is a minimal working example deserializing the XML to a single POS
instance with an ArrayCollection
of POS_Source
instances. I threw away all normalizers etc. not essential for deserializing this particular XML.
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
class POS
{
// ... just as in the question ...
}
/**
* Minimal implementation of POS_Source for purposes of this deserialization example.
*/
class POS_Source
{
private $RequestorID;
public function setPOS(POS $POS)
{
}
public function getRequestorID()
{
return $this->RequestorID;
}
public function setRequestorID($RequestorID)
{
$this->RequestorID = $RequestorID;
}
}
$data = '<POS>
<!-- ... the same XML as in the question ... -->
</POS>';
$normalizers = [
new ArrayDenormalizer(),
new ObjectNormalizer(null, null, null, new ReflectionExtractor())
];
$encoders = [new XmlEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$pos = $serializer->deserialize($data,POS::class,'xml');
dump($pos);
Prints:
POS {#14
-Source: Doctrine\Common\Collections\ArrayCollection {#11
-elements: array:4 [
0 => POS_Source {#17
-RequestorID: array:3 [
"@Type" => 11
"@ID" => "T921"
"CompanyName" => array:3 [
"@Code" => "CP"
"@CodeContext" => "123T"
"#" => ""
]
]
}
1 => POS_Source {#27
-RequestorID: array:3 [
"@Type" => 1
"@ID" => 34778
"#" => ""
]
}
2 => POS_Source {#22
-RequestorID: array:3 [
"@Type" => 9
"@ID" => "ZF"
"#" => ""
]
}
3 => POS_Source {#25
-RequestorID: array:3 [
"@Type" => 17
"@ID" => "mabaan"
"#" => ""
]
}
]
}
}