JMSSerializerBundle
JMSSerializerBundle copied to clipboard
Cannot fully serialized a property with type ArrayCollection<abstract type>
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
Hello @Vicente69, have you found a solution of this problem?
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
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()));
}
}