10
votes

When I deserialize my doctrine entity, the initial object is constructed/initiated correctly, however all child relations are trying to be called as arrays.

The root level object's addChild(ChildEntity $entity) method is being called, but Symfony is throwing an error that addChild is receiving an array and not an instance of ChildEntity.

Does Symfony's own serializer have a way to deserialize nested arrays (child entities) to the entity type?

JMS Serializer handles this by specifying a @Type("ArrayCollection<ChildEntity>") annotation on the property.

2
Hey, did you find a way?Albert Casadessús

2 Answers

1
votes

I believe the Symfony serializer attempts to be minimal compared to the JMS Serializer, so you might have to implement your own denormalizer for the class. You can see how the section on adding normalizers.

0
votes

There may be an easier way, but so far with Symfony I am using Discriminator interface annotation and type property for array of Objects. It can also handle multiple types in one array (MongoDB):

namespace App\Model;

use Symfony\Component\Serializer\Annotation\DiscriminatorMap;

/**
 * @DiscriminatorMap(typeProperty="type", mapping={
 *    "text"="App\Model\BlogContentTextModel",
 *    "code"="App\Model\BlogContentCodeModel"
 * })
 */
interface BlogContentInterface
{
    /**
     * @return string
     */
    public function getType(): string;
}

and parent object will need to define property as interface and get, add, remove methods:

    /**
     * @var BlogContentInterface[]
     */
    protected $contents = [];
    
    /**
     * @return BlogContentInterface[]
     */
    public function getContents(): array
    {
        return $this->contents;
    }

    /**
     * @param BlogContentInterface[] $contents
     */
    public function setContents($contents): void
    {
        $this->contents = $contents;
    }

    /**
     * @param BlogContentInterface $content
     */
    public function addContent(BlogContentInterface $content): void
    {
        $this->contents[] = $content;
    }

    /**
     * @param BlogContentInterface $content
     */
    public function removeContent(BlogContentInterface $content): void
    {
        $index = array_search($content, $this->contents);
        if ($index !== false) {
            unset($this->contents[$index]);
        }
    }