Closed
Description
Symfony version(s) affected: 5.x and most likely earlier versions
Description
The Serializer::serialize()
with JsonEncoder
don't care about child classes which causes issues when deserializing. See #33394
How to reproduce
<?php
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
use Symfony\Component\Serializer\Serializer;
require __DIR__.'/vendor/autoload.php';
class Animal
{
private $sound;
public function __construct($sound)
{
$this->sound = $sound;
}
public function __toString(): string
{
return (string) $this->sound;
}
/**
* Without this method, the "deserialize()" will fail with:
* > Fatal error: Uncaught Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException:
* > Cannot create an instance of "Animal" from serialized data because its
* > constructor requires parameter "sound" to be present.
*/
public function getSound()
{
return $this->sound;
}
}
class Fox extends Animal
{
private $color;
private $name;
public function getColor()
{
return $this->color;
}
public function setColor($color): void
{
$this->color = $color;
}
public function getName()
{
return $this->name;
}
public function setName($name): void
{
$this->name = $name;
}
}
class Wrapper
{
private $animal;
public function __construct(Animal $animal)
{
$this->animal = $animal;
}
public function getAnimal(): Animal
{
return $this->animal;
}
}
$serializer = new Serializer([new UnwrappingDenormalizer(new PropertyAccessor()), new ObjectNormalizer()], ['json' => new JsonEncoder()]);
$fox = new Fox('???');
$fox->setName('Foobar');
$fox->setColor('Red');
$data = $serializer->serialize(new Wrapper($fox), 'json');
var_dump($data);
$result = $serializer->deserialize($data, Wrapper::class, 'json');
var_dump($result);
php test.php
string(56) "{"animal":{"color":"Red","name":"Foobar","sound":"???"}}"
object(Wrapper)#32 (1) {
["animal":"Wrapper":private]=>
object(Animal)#38 (1) {
["sound":"Animal":private]=>
string(3) "???"
}
}
The wrapper should contain a Fox
, not an Animal
.