I'm trying to deserialize an XML-file to an object containing an array of other objects using Symfony Serializer, but can't get it to work with an array of objects under a specific key.
Here's a simplified version of the XML:
<?xml version="1.0"?>
<ROOT>
<RETURN>
<TYPE>test</TYPE>
</RETURN>
<COMPONENT>
<item>
<ID>1</ID>
</item>
<item>
<ID>2</ID>
</item>
</COMPONENT>
</ROOT>
I have a class which I'd like to deserialize this to. It looks like this:
class MyObject
{
private Return $return;
/** @var array<Component> */
private array $component = [];
// getters and setters here
}
The class "Return" has a "type"-property, the class "Component" has an "id", both with getters and setters.
This is my (current) serializer:
$serializer = new Serializer(
[
new ArrayDenormalizer(),
new ObjectNormalizer(propertyTypeExtractor: new ReflectionExtractor()),
],
[new XmlEncoder()]
);
Deserializing my XML will now produce the following result:
^ App\ValueObject\MyObject^ {
-return: App\ValueObject\Return^ {
-type: "test"
}
-component: array:1 [
"item" => array:2 [
0 => array:1 [
"ID" => "1"
],
1 => array:1 [
"ID" => "2"
(...)
while the expected output is this:
^ App\ValueObject\MyObject^ {
-return: App\ValueObject\Return^ {
-type: "test"
}
-component: array:2 [
0 => App\ValueObject\Component^ {
-id: "1"
},
1 => App\ValueObject\Component^ {
-id: "2"
}
(...)
So deserializing the Return-object works as expected, mapping the XML to my array of Component-objects does not.
(Also I noticed that if my component only has one item, the output is not "-component: array:1 [ "item" => array:1 [ 0 => array:1 [ "ID" => "1" ] ]" but "-component: array:1 [ "item" => array:1 [ "ID" => "1" ] ]", so there's one level missing.)
Based on several tutorials and answers here I have tried using this as my extractors:
$phpDocExtractor = new PhpDocExtractor();
$typeExtractor = new PropertyInfoExtractor(
typeExtractors: [new ConstructorExtractor([$phpDocExtractor]), $phpDocExtractor, new ReflectionExtractor()]
);
which will produce this:
-component: array:1 [
0 => App\ValueObject\Component^ {
-id: ""
so there's only one Component-object (instead of an array of 2), also it is empty (id is missing). The same thing happens, if I just use the PhpDocExptractor or add a GetSetMethodNormalizer with a PhpDocExtractor or ReflectionExtractor.
I also played around with the @var-comment for $component, using "array<array<Component>>", but that does not change anything.
Next stop: Based on this post I converted my $component to ArrayCollection and added addComponent and removeComponent to the Component-class, but nothing changes, the addComponent-function is only called once with an array of arrays which are not deserialized to my Component-class.
It seems that deserializing objects into an array of objects is possible somehow (as the enhanced serializer shows), but somehow I'm missing the right combination of extractors (I guess). Or is it a naming problem in the XML? Do I need to have <components> as parent and <component> as child keys instead of <component> and <item>? (Which unfortunately I could not change as the XML is coming from a remote system - but can I tell the Serializer about my structure to make it understand the keys better?)