Serializing Entity Relation only to Id with JMS Serializer

后端 未结 6 605
温柔的废话
温柔的废话 2021-02-02 09:54

I\'m trying to serialize a entity relation with JMS Serializer.

Here is the Entity:

class Ad
{ 

    /**
     * @Type(\"string\")
     * @Groups({\"manag         


        
6条回答
  •  渐次进展
    2021-02-02 10:25

    Just to follow answered question:

    If you don't like writing one method for each relation you have - just write your own handler. It's easy like

    final class RelationsHandler
    {
        /**
         * @var EntityManagerInterface
         */
        private $manager;
    
        /**
         * RelationsHandler constructor.
         *
         * @param EntityManagerInterface $manager
         */
        public function __construct(EntityManagerInterface $manager) { $this->manager = $manager; }
    
    
        public function serializeRelation(JsonSerializationVisitor $visitor, $relation, array $type, Context $context)
        {
            if ($relation instanceof \Traversable) {
                $relation = iterator_to_array($relation);
            }
    
            if (is_array($relation)) {
                return array_map([$this, 'getSingleEntityRelation'], $relation);
            }
    
            return $this->getSingleEntityRelation($relation);
        }
    
        /**
         * @param $relation
         *
         * @return array|mixed
         */
        protected function getSingleEntityRelation($relation)
        {
            $metadata = $this->manager->getClassMetadata(get_class($relation));
    
            $ids = $metadata->getIdentifierValues($relation);
            if (!$metadata->isIdentifierComposite) {
                $ids = array_shift($ids);
            }
    
            return $ids;
        }
    }
    

    Register the Handler

      jms_serializer.handler.relation:
          class: MyBundle\RelationsHandler
          arguments:
          - "@doctrine.orm.entity_manager"
          tags:
          - { name: jms_serializer.handler, type: Relation, direction: serialization, format: json, method: serializeRelation}
          - { name: jms_serializer.handler, type: Relation, direction: deserialization, format: json, method: deserializeRelation}
          - { name: jms_serializer.handler, type: Relation, direction: serialization, format: json, method: serializeRelation}
          - { name: jms_serializer.handler, type: Relation, direction: deserialization, format: json, method: deserializeRelation}
    

    This allows you to replace virtual getter methods with `Type("Relation").

    If you also want't to deserialize relation - you should tell each @Type("Relation") the classname (@Type("Relation")) which it should deserialize to or wrap the metadata driver with one which do it for you.

        public function deserializeRelation(JsonDeserializationVisitor $visitor, $relation, array $type, Context $context)
        {
            $className = isset($type['params'][0]['name']) ? $type['params'][0]['name'] : null;
    
            if (!class_exists($className, false)) {
                throw new \InvalidArgumentException('Class name should be explicitly set for deserialization');
            }
    
            $metadata = $this->manager->getClassMetadata($className);
    
            if (!is_array($relation)) {
                return $this->manager->getReference($className, $relation);
            }
    
            $single = false;
            if ($metadata->isIdentifierComposite) {
                $single = true;
                foreach ($metadata->getIdentifierFieldNames() as $idName) {
                    $single = $single && array_key_exists($idName, $relation);
                }
            }
    
            if ($single) {
                return $this->manager->getReference($className, $relation);
            }
    
            $objects = [];
            foreach ($relation as $idSet) {
                $objects[] = $this->manager->getReference($className, $idSet);
            }
    
            return $objects;
        }
    

提交回复
热议问题