public function onPreSerialize(PreSerializeEvent $event)
 {
     $object = $event->getObject();
     if ($object instanceof PersistentCollection) {
         $event->setType('ArrayCollection');
         return;
     }
     if (!$object instanceof Proxy && !$object instanceof ORMProxy) {
         return;
     }
     $object->__load();
     $event->setType(get_parent_class($object));
 }
 /**
  * Called for each node of the graph that is being traversed.
  *
  * @param mixed $data the data depends on the direction, and type of visitor
  * @param array|null $type array has the format ["name" => string, "params" => array]
  * @param VisitorInterface $visitor
  *
  * @return mixed the return value depends on the direction, and type of visitor
  */
 public function accept($data, array $type = null, VisitorInterface $visitor)
 {
     // If the type was not given, we infer the most specific type from the
     // input data in serialization mode.
     if (null === $type) {
         if (self::DIRECTION_DESERIALIZATION === $this->direction) {
             $msg = 'The type must be given for all properties when deserializing.';
             if (null !== ($path = $this->getCurrentPath())) {
                 $msg .= ' Path: ' . $path;
             }
             throw new \RuntimeException($msg);
         }
         $typeName = gettype($data);
         if ('object' === $typeName) {
             $typeName = get_class($data);
         }
         $type = array('name' => $typeName, 'params' => array());
     }
     switch ($type['name']) {
         case 'NULL':
             return $visitor->visitNull($data, $type);
         case 'string':
             return $visitor->visitString($data, $type);
         case 'integer':
             return $visitor->visitInteger($data, $type);
         case 'boolean':
             return $visitor->visitBoolean($data, $type);
         case 'double':
             return $visitor->visitDouble($data, $type);
         case 'array':
             return $visitor->visitArray($data, $type);
         case 'resource':
             $msg = 'Resources are not supported in serialized data.';
             if (null !== ($path = $this->getCurrentPath())) {
                 $msg .= ' Path: ' . implode(' -> ', $path);
             }
             throw new \RuntimeException($msg);
         default:
             $isSerializing = self::DIRECTION_SERIALIZATION === $this->direction;
             if ($isSerializing && null !== $data) {
                 if ($this->visiting->contains($data)) {
                     return null;
                 }
                 $this->visiting->attach($data);
             }
             // First, try whether a custom handler exists for the given type. This is done
             // before loading metadata because the type name might not be a class, but
             // could also simply be an artifical type.
             if (null !== ($handler = $this->handlerRegistry->getHandler($this->direction, $type['name'], $this->format))) {
                 $rs = call_user_func($handler, $visitor, $data, $type);
                 if ($isSerializing) {
                     $this->visiting->detach($data);
                 }
                 return $rs;
             }
             // Trigger pre-serialization callbacks, and listeners if they exist.
             if ($isSerializing) {
                 if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_serialize', $type['name'], $this->format)) {
                     $this->dispatcher->dispatch('serializer.pre_serialize', $type['name'], $this->format, $event = new PreSerializeEvent($visitor, $data, $type));
                     $type = $event->getType();
                 }
             }
             // Load metadata, and check whether this class should be excluded.
             $metadata = $this->metadataFactory->getMetadataForClass($type['name']);
             if (null !== $this->exclusionStrategy && $this->exclusionStrategy->shouldSkipClass($metadata, $isSerializing ? $data : null)) {
                 if ($isSerializing) {
                     $this->visiting->detach($data);
                 }
                 return null;
             }
             if ($isSerializing) {
                 foreach ($metadata->preSerializeMethods as $method) {
                     $method->invoke($data);
                 }
             }
             $object = $data;
             if (!$isSerializing) {
                 $object = $this->objectConstructor->construct($visitor, $metadata, $data, $type);
             }
             if (isset($metadata->handlerCallbacks[$this->direction][$this->format])) {
                 $rs = $object->{$metadata->handlerCallbacks[$this->direction][$this->format]}($visitor, $isSerializing ? null : $data);
                 $this->afterVisitingObject($visitor, $metadata, $object, $type);
                 return $isSerializing ? $rs : $object;
             }
             $visitor->startVisitingObject($metadata, $object, $type);
             foreach ($metadata->propertyMetadata as $propertyMetadata) {
                 if (null !== $this->exclusionStrategy && $this->exclusionStrategy->shouldSkipProperty($propertyMetadata, $isSerializing ? $data : null)) {
                     continue;
                 }
                 if (!$isSerializing && $propertyMetadata->readOnly) {
                     continue;
                 }
                 $visitor->visitProperty($propertyMetadata, $data);
             }
             if ($isSerializing) {
                 $this->afterVisitingObject($visitor, $metadata, $data, $type);
                 return $visitor->endVisitingObject($metadata, $data, $type);
             }
             $rs = $visitor->endVisitingObject($metadata, $data, $type);
             $this->afterVisitingObject($visitor, $metadata, $rs, $type);
             return $rs;
     }
 }