phpjmsserializerbundlejms-serializer

Deserializer does only work with additional tag


I want do deserialize an XML-Feed to a list of Objects. Here are my classes

namespace App\Test;

use JMS\Serializer\SerializerInterface;

class Test
{
    public function __construct(private readonly SerializerInterface $serializer)
    {
    }

    public function test()
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>
<items>
        <item><id>1</id></item>
        <item><id>2</id></item>
       </items> 
        ';

        $o = $this->serializer->deserialize($xml, Items::class, 'xml');
       dump($o);
    }
}

namespace App\Test;
use JMS\Serializer\Annotation as Serializer;
class Items {
    #[Serializer\Type(ItemList::class)]
    #[Serializer\SerializedName('items')]
    protected ItemList $items;
}
namespace App\Test;

use JMS\Serializer\Annotation as Serializer;
class ItemList {
    #[Serializer\XmlList(entry: 'item', inline: true)]
    #[Serializer\Type('array<App\Test\Item>')]
    protected array $items;
}

namespace App\Test;
use JMS\Serializer\Annotation as Serializer;
class Item {
    #[Serializer\SerializedName('id')]
    protected int $id;
}

When I run Test.php, it dumps an empty Items object. But when I add an additional Tag to the XML, it works


        $xml = '<?xml version="1.0" encoding="UTF-8"?><X>
<items>
        <item><id>1</id></item>
        <item><id>2</id></item>
       </items> </X>
        ';

Using this additional tag is a very dirty hack, so how do I have to configure my setup? Using this one: How to deserialize XML to an object that contains an array collection in php Symfony did not help me neither. I am using Symfony version 6.3.4


Solution

  • I made the main changes in the Items and ItemList classes.

    In the Items class, open a method called getItems that uses ItemList and returns the list of items. This will cause the JMS Serializer to use getItems when trying to deserialize Items instead of trying to access the ItemList directly.

    In the ItemList class, we have added the same getItems method that returns the list of items. This method ensures that we can easily access the list of items.

    With these changes, the JMS Serializer can accurately deserialize the list of items and return you an Items object with the correct values.

    like this :

    class ItemList
    {
        #[Serializer\XmlList(entry: 'item', inline: true)]
        #[Serializer\Type('array<App\Test\Item>')]
        private array $items;
    
        public function getItems(): array
        {
            return $this->items;
        }
    }
    
    
    
    namespace App\Test;
    
    use JMS\Serializer\Annotation as Serializer;
    
    class Items {
        #[Serializer\Type(ItemList::class)]
        #[Serializer\SerializedName('items')]
        private ItemList $items;
    
        public function getItems(): array
        {
            return $this->items->getItems();
        }
    }