Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialization fails when discriminator base class extends another class #182

Closed
gregory90 opened this issue Nov 19, 2013 · 4 comments
Closed
Labels

Comments

@gregory90
Copy link

This code:

abstract class Thing {}

/**
* @Serializer\Discriminator(field = "type", map = {
*    "car": "Car",
*    "moped": "Moped",
* })
**/
abstract class Vehicle extends Thing
{
    /** @Serializer\Type("integer") */
    public $km;

    public function __construct($km)
    {
            $this->km = (integer) $km;
    }
}

class Moped extends Vehicle
{
}

class Car extends Vehicle
{
}

$jsonData = '{"km":5,"type":"car"}';
$serializer = JMS\Serializer\SerializerBuilder::create()->build();

$object = $serializer->deserialize($jsonData, 'Vehicle', 'json');

Fails with:

PHP Fatal error: Cannot instantiate abstract class Vehicle in .../jms/serializer/src/JMS/Serializer/Construction/UnserializeObjectConstructor.php on line 28

Am I missing something?

@jaymecd
Copy link
Contributor

jaymecd commented Feb 23, 2014

Same here, after small research I noticed that base class (in this case Vehicle) looses discriminatorMap and other related metadata, while it extends other class.

According to the doc its not allowed to define @Discriminator on derived class, only on top class in chain, what makes life sometimes harder.

This is var_dump($metadata) output without extend:

class JMS\Serializer\Metadata\ClassMetadata 
{
    ...
    public $discriminatorDisabled => bool(false)
    public $discriminatorBaseClass => string(7) "Vehicle"
    public $discriminatorFieldName => string(4) "type"
    public $discriminatorValue => string(4) "car"
    public $discriminatorMap => array(2) {
        'car' =>  string(3) "Car",
        'moped' =>  string(5) "Moped"
    }
    ...
}

This is var_dump($metadata) output with extend:

class JMS\Serializer\Metadata\ClassMetadata 
{
    ...
    public $discriminatorDisabled => bool(false)
    public $discriminatorBaseClass => NULL
    public $discriminatorFieldName => NULL 
    public $discriminatorValue => NULL
    public $discriminatorMap => array(0) {}
    ...
}

@mnapoli
Copy link

mnapoli commented Jun 4, 2014

Same here (btw not related to #56), that's a problem if you have a base entity class.

@goetas
Copy link
Collaborator

goetas commented Sep 9, 2016

solved by #382

@goetas goetas closed this as completed Sep 9, 2016
@coyl
Copy link

coyl commented Sep 19, 2016

Still reproducing:

class Foo{}
/**
 * @Serializer\Discriminator(field = "type", map = {"car": "Car", "moped": "Moped"})
 */
abstract class Vehicle extends Foo { }
class Car extends Vehicle { }
class Moped extends Vehicle { }
....
$job = new Moped();
/** @var SerializerInterface $ser */
$data = $ser->serialize($job, 'json');

echo $data;
$job = $ser->deserialize($data, Vehicle::class, 'json');

output

{
    "type": "moped"
}

  [Doctrine\Instantiator\Exception\InvalidArgumentException]                                        
  The provided class "Vehicle" is abstract, and can not be instantiated  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants