How to encode Doctrine entities to JSON in Symfony 2.0 AJAX application?

Viewed 133178

I'm developing game app and using Symfony 2.0. I have many AJAX requests to the backend. And more responses is converting entity to JSON. For example:

class DefaultController extends Controller
{           
    public function launchAction()
    {   
        $user = $this->getDoctrine()
                     ->getRepository('UserBundle:User')                
                     ->find($id);

        // encode user to json format
        $userDataAsJson = $this->encodeUserDataToJson($user);
        return array(
            'userDataAsJson' => $userDataAsJson
        );            
    }

    private function encodeUserDataToJson(User $user)
    {
        $userData = array(
            'id' => $user->getId(),
            'profile' => array(
                'nickname' => $user->getProfile()->getNickname()
            )
        );

        $jsonEncoder = new JsonEncoder();        
        return $jsonEncoder->encode($userData, $format = 'json');
    }
}

And all my controllers do the same thing: get an entity and encode some of its fields to JSON. I know that I can use normalizers and encode all entitities. But what if an entity has cycled links to other entity? Or the entities graph is very big? Do you have any suggestions?

I think about some encoding schema for entities... or using NormalizableInterface to avoid cycling..,

13 Answers

in Symfony 2.3

/app/config/config.yml

framework:
    # сервис конвертирования объектов в массивы, json, xml и обратно
    serializer:
        enabled: true

services:
    object_normalizer:
        class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
        tags:
        # помечаем к чему относится этот сервис, это оч. важно, т.к. иначе работать не будет
          - { name: serializer.normalizer }

and example for your controller:

/**
 * Поиск сущности по ИД объекта и ИД языка
 * @Route("/search/", name="orgunitSearch")
 */
public function orgunitSearchAction()
{
    $array = $this->get('request')->query->all();

    $entity = $this->getDoctrine()
        ->getRepository('IntranetOrgunitBundle:Orgunit')
        ->findOneBy($array);

    $serializer = $this->get('serializer');
    //$json = $serializer->serialize($entity, 'json');
    $array = $serializer->normalize($entity);

    return new JsonResponse( $array );
}

but the problems with the field type \DateTime will remain.

The accepted answer is correct but if You'll need to serialize a filtered subset of an Entity , json_encode is enough:

Consider this example:

class FileTypeRepository extends ServiceEntityRepository  
{

   const ALIAS = 'ft';
   const SHORT_LIST = 'ft.name name';

    public function __construct(ManagerRegistry $registry)
    {
         parent::__construct($registry, FileType::class);
    }

    public function getAllJsonFileTypes() 
    {
        return json_encode($this->getAllFileTypes());
    } 

   /**
    * @return array
    */
    public function getAllFileTypes()
    {
        $query = $this->createQueryBuilder(self::ALIAS);
        $query->select(self::SHORT_LIST);
        return $query->getQuery()->getResult();
    }
}



/** THIS IS ENOUGH TO SERIALIZE AN ARRAY OF ENTITIES SINCE the doctrine SELECT will remove complex data structures from the entities itself **/
json_encode($this->getAllFileTypes()); 

Short note: Tested at least on Symfony 5.1

Related