JMSSerializerBundle icon indicating copy to clipboard operation
JMSSerializerBundle copied to clipboard

Cannot fully serialized a property with type ArrayCollection<abstract type>

Open v1nc3n4 opened this issue 11 years ago • 3 comments

Hi,

I'm working with inheritance, and I cannot succeed in serializing an ArrayCollection property of an abstract type, using YAML configuration. For instance:

// This is the main class being serialized
class Entity
{
    private $elements;
}

The Entity class has this serializer configuration:

Entity:
    properties:
        elements:
            type: 'ArrayCollection<AbstractElement>'

The collection contains instances of this abstract class:

abstract class AbstractElement
{
    // A successfully serialized property.
    private $id;

    /**
     * @return mixed The data in this model. It's up to each concrete sub-class to define
     * the exact type returned.
     */
    public abstract function getValue();
}

The AbstractElement class has this serializer configuration:

AbstractElement:
    properties:
        id:
            type: integer

A concrete implementation of this abstract class is:

class Element extends AbstractElement
{
    // This property is never serialized!
    $private $value;
}

The Element class has this serializer configuration:

Element:
    properties:
        value:
            type: string

The property 'value' in the Element class is never serialized, when attempting to serialize an instance of the Entity class containing one element. It seems that drivers don't look at all configuration files, for each class in the hierarchy. Drivers look only at the 'AbstractElement' metadata defined in 'ArrayCollection<AbstractElement>', and don't see the 'value' property in the Element sub-class. Thus, my question is simple: are abstraction and inheritance supported when serializing collections? Feel free to tell me if I've done something wrong!

Thanks in advance for your help. BR

v1nc3n4 avatar Feb 21 '14 14:02 v1nc3n4

Hello @Vicente69, have you found a solution of this problem?

goth-pl avatar Apr 05 '14 17:04 goth-pl

Hello @goth-pl,

I didn't find a fully acceptable solution for this problem. However, as an intermediate solution, I used the serializer 'virtual_properties' key in the AbstractElement class, and its configuration for the serializer now is:

AbstractElement
    virtual_properties:
        getValue: {}
properties:
        id:
            type: integer

In this example, the Element class now has no configuration anymore. This solution is not fully acceptable for me because it is not possible to specify the exact type returned by the implementation of the getValue method, in the Element class.

BR

v1nc3n4 avatar Apr 08 '14 20:04 v1nc3n4

A better work around is to do a jms listener and change the type of the object during the onPreSerialize event. It's still ugly but at least the concern of this issue is separated from the configuration file.

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

mpoiriert avatar Mar 12 '16 21:03 mpoiriert