JMSSerializerBundle: @Discriminator Error: The error is: The discriminator field name "type" for base-class "MyBundle\Entity\MyClass" was not found in input data

Hi, i have a problem with @discriminator for abstract class. For example, this structure of classes don’t work correctly when I try to serialize and deserialize the objects.

class Saloon
{
    /**
     *@Type("integer")
     */
    public $id;

    /**
     * @Type("MyME\HelloBundle\Controller\Vehicle")
     */
    public $veichle;
}


/**
 * @Discriminator(field = "type", map = {"car": "MyME\HelloBundle\Controller\Car", * "moped":"MyME\HelloBundle\Controller\Moped"})
 */
abstract class Vehicle {

    public $id;


}
class Car extends Vehicle {

    /**
     *@Type("integer")
    */
    public $id;
    /**
     *@Type("string")
     */
    public $car_at;
}
class Moped extends Vehicle {

    /**
     *@Type("integer")
     */
    public $id;
    /**
     *@Type("string")
     */
    public $moped_at;

}

example usage:

        $car = new Car();
        $car->id = 1; 
        $car->car_at = "car";

        $car2 = new Moped();
        $car2->id = 2; 
        $car2->moped_at = "moped";


        $saloon = new Saloon();
        $sal0on->veichle = $car2;
        $serializer = SerializerBuilder::create()->build();
        $jsonveic = $serializer->serialize($saloon,'json');

        $saloon_des = $serializer->deserialize($jsonveic,'MyME\HelloBundle\Controller\Saloon','json');

The error is: The discriminator field name “type” for base-class “MyME\HelloBundle\Controller\Vehicle” was not found in input data

About this issue

  • Original URL
  • State: open
  • Created 11 years ago
  • Reactions: 1
  • Comments: 74

Commits related to this issue

Most upvoted comments

Hi I also faced with this issue. As a workaround i use such a listener

namespace Acme\Bundle\DemoBundle\EventListener;

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;

class JMSSerializerListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            ['event' => Events::PRE_SERIALIZE, 'method' => 'onPreSerialize']
        ];
    }

    /**
     * @param PreSerializeEvent $event
     */
    public function onPreSerialize(PreSerializeEvent $event)
    {
        $object = $event->getObject();
        if (is_object($object) &&
            is_subclass_of($object, 'Acme\Bundle\DemoBundle\Entity\ParentEntity') &&
            get_class($object) !== $event->getType()['name']
        ) {
            $event->setType(get_class($event->getObject()));
        }
    }
}

With this listener it works fine.

After some investigation, it seems the serialization process does not recognize the discrimination properly.

When serializing the concrete class, the visitor visits the concrete class configuration. But when serializing the class which embeds the discriminated object, only the visitor for the abstract class is triggered.

I think this is a bug, because when deserializing it is working as intended. I just don’t know if that’s “another” bug which has not much to do with the one described in the ticket 😉

Look at the @Serializer\VirtualProperty Annotation. Worked for me.

class Car extends Vehicle {
    /**
     * @Serializer\VirtualProperty
     */
    public function getType()
    {
        return 'car';
    }
}

class Moped extends Vehicle {
    /**
     * @Serializer\VirtualProperty
     */
    public function getType()
    {
        return 'moped';
    }
}